Go to the documentation of this file.00001
00026 #include "WindowsSocket.h"
00027 #include <string>
00028 #include <iostream>
00029 #include <winsock2.h>
00030 #include <ws2tcpip.h>
00031
00032 #pragma comment(lib, "Ws2_32.lib")
00033
00034 #define DEFAULT_PORT "11411"
00035
00036 using std::string;
00037 using std::cerr;
00038 using std::endl;
00039
00040
00041 class WindowsSocketImpl
00042 {
00043
00044 public:
00045
00046 WindowsSocketImpl () : mySocket (INVALID_SOCKET)
00047 { }
00048
00049 void init (char *server_hostname)
00050 {
00051 WSADATA wsaData;
00052 int result = WSAStartup (MAKEWORD (2, 2), &wsaData);
00053 if (result)
00054 {
00055
00056 std::cerr << "Could not initialize windows socket (" << result << ")" << std::endl;
00057 return;
00058 }
00059
00060 struct addrinfo *servers = get_server_addr (server_hostname);
00061
00062 if (NULL == servers)
00063 {
00064 WSACleanup ();
00065 return;
00066 }
00067
00068 connect_to_server (servers);
00069
00070 freeaddrinfo (servers);
00071
00072 if (INVALID_SOCKET == mySocket)
00073 {
00074 std::cerr << "Could not connect to server" << std::endl;
00075 WSACleanup ();
00076 }
00077 }
00078
00079 int read ()
00080 {
00081 char data;
00082 int result = recv (mySocket, &data, 1, 0);
00083 if (result < 0)
00084 {
00085 if (WSAEWOULDBLOCK != WSAGetLastError())
00086 {
00087 std::cerr << "Failed to receive data from server " << WSAGetLastError() << std::endl;
00088 }
00089 return -1;
00090 }
00091 else if (result == 0)
00092 {
00093 std::cerr << "Connection to server closed" << std::endl;
00094 return -1;
00095 }
00096 return (unsigned char) data;
00097 }
00098
00099 void write (const unsigned char *data, int length)
00100 {
00101 int result = send (mySocket, (const char *) data, length, 0);
00102 if (SOCKET_ERROR == result)
00103 {
00104 std::cerr << "Send failed with error " << WSAGetLastError () << std::endl;
00105 closesocket (mySocket);
00106 WSACleanup ();
00107 }
00108 }
00109
00110 unsigned long time ()
00111 {
00112 SYSTEMTIME st_now;
00113 GetSystemTime (&st_now);
00114 unsigned long millis = st_now.wHour * 3600000 +
00115 st_now.wMinute * 60000 +
00116 st_now.wSecond * 1000 +
00117 st_now.wMilliseconds;
00118 return millis;
00119 }
00120
00121 protected:
00129 struct addrinfo *get_server_addr (const string & hostname)
00130 {
00131 int result;
00132 struct addrinfo *ai_output = NULL;
00133 struct addrinfo ai_input;
00134
00135
00136 int c = hostname.find_last_of (':');
00137 string host = hostname.substr (0, c);
00138 string port = (c < 0) ? DEFAULT_PORT : hostname.substr (c + 1);
00139
00140 ZeroMemory (&ai_input, sizeof (ai_input));
00141 ai_input.ai_family = AF_UNSPEC;
00142 ai_input.ai_socktype = SOCK_STREAM;
00143 ai_input.ai_protocol = IPPROTO_TCP;
00144
00145
00146 result = getaddrinfo (host.c_str (), port.c_str (), &ai_input, &ai_output);
00147 if (result != 0)
00148 {
00149 std::cerr << "Could not resolve server address (" << result << ")" << std::endl;
00150 return NULL;
00151 }
00152 return ai_output;
00153 }
00154
00159 void connect_to_server (struct addrinfo *servers)
00160 {
00161 int result;
00162 for (struct addrinfo * ptr = servers; ptr != NULL; ptr = ptr->ai_next)
00163 {
00164 mySocket = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
00165 if (INVALID_SOCKET == mySocket)
00166 {
00167 std::cerr << "Could not great socket " << WSAGetLastError ();
00168 return;
00169 }
00170
00171 result = connect (mySocket, ptr->ai_addr, (int) ptr->ai_addrlen);
00172 if (SOCKET_ERROR == result)
00173 {
00174 closesocket (mySocket);
00175 mySocket = INVALID_SOCKET;
00176 }
00177 else
00178 {
00179 break;
00180 }
00181 }
00182
00183
00184 char value = 1;
00185 setsockopt (mySocket, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value));
00186
00187 u_long iMode = 1;
00188 result = ioctlsocket (mySocket, FIONBIO, &iMode);
00189 if (result)
00190 {
00191 std::cerr << "Could not make socket nonblocking " << result << std::endl;
00192 closesocket (mySocket);
00193 mySocket = INVALID_SOCKET;
00194 }
00195 }
00196
00197 private:
00198 SOCKET mySocket;
00199 };
00200
00201 WindowsSocket::WindowsSocket ()
00202 {
00203 impl = new WindowsSocketImpl ();
00204 }
00205
00206 void WindowsSocket::init (char *server_hostname)
00207 {
00208 impl->init (server_hostname);
00209 }
00210
00211 int WindowsSocket::read ()
00212 {
00213 return impl->read ();
00214 }
00215
00216 void WindowsSocket::write (const unsigned char *data, int length)
00217 {
00218 impl->write (data, length);
00219 }
00220
00221 unsigned long WindowsSocket::time ()
00222 {
00223 return impl->time ();
00224 }