Platform_Win32_Network_Client.cpp
Go to the documentation of this file.00001 //*** Platform_Win32_Network_Client.cpp *** 00002 00003 #define WIN32_LEAN_AND_MEAN 00004 #define VC_EXTRALEAN 00005 #include <winsock2.h> 00006 00007 #pragma warning (push) 00008 #pragma warning( disable: 4127) 00009 #pragma warning( disable: 4706) 00010 #include <ws2tcpip.h> 00011 #pragma warning (pop) 00012 00013 #include "Platform_Win32_Network_Client.h" 00014 00015 #include "Platform_Win32_Network.h" 00016 #include "Debug.h" 00017 #include "StandardLibrary.h" 00018 00019 00020 //*** Constructor (listening) *** 00021 00022 Platform_Win32_Network_Client::Platform_Win32_Network_Client(Platform_Win32_Network* network, Platform_Network::ConnectionMode mode, const char* address, int port): 00023 network_(network), 00024 mode_(mode), 00025 address_(0), 00026 port_(port), 00027 socket_(INVALID_SOCKET), 00028 connected_(false), 00029 waitingToConnect_(false), 00030 maxMessageSize_(0) 00031 { 00032 // Save the address 00033 address_=StrDup(address); 00034 } 00035 00036 00037 //*** Destructor *** 00038 00039 Platform_Win32_Network_Client::~Platform_Win32_Network_Client() 00040 { 00041 // Disconnect 00042 if (socket_!=INVALID_SOCKET) 00043 { 00044 if (closesocket(socket_)!=0) 00045 { 00046 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00047 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00048 } 00049 socket_=INVALID_SOCKET; 00050 } 00051 00052 // Notify manager 00053 network_->ClientDestroyed(this); 00054 00055 // Free address 00056 if (address_) 00057 { 00058 Free(const_cast<char*>(address_)); 00059 } 00060 } 00061 00062 00063 //*** GetConnectionMode *** 00064 00065 Platform_Network::ConnectionMode Platform_Win32_Network_Client::GetConnectionMode() 00066 { 00067 return mode_; 00068 } 00069 00070 00071 //*** GetAddress *** 00072 00073 const char* Platform_Win32_Network_Client::GetAddress() 00074 { 00075 return address_; 00076 } 00077 00078 00079 //*** GetPort *** 00080 00081 int Platform_Win32_Network_Client::GetPort() 00082 { 00083 return port_; 00084 } 00085 00086 00087 //*** Connect *** 00088 00089 bool Platform_Win32_Network_Client::Connect() 00090 { 00091 // Close existing connection 00092 if (socket_!=INVALID_SOCKET) 00093 { 00094 if (closesocket(socket_)!=0) 00095 { 00096 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00097 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00098 } 00099 socket_=INVALID_SOCKET; 00100 connected_=false; 00101 waitingToConnect_=false; 00102 } 00103 00104 // Reset receive buffer 00105 receivedData_.Clear(false); 00106 00107 // Set up hints for getaddrinfo 00108 addrinfo hints; 00109 MemSet(&hints,0,sizeof(hints)); 00110 hints.ai_family = AF_UNSPEC; // The Internet Protocol version 4 (IPv4) address family. 00111 hints.ai_flags = AI_PASSIVE; 00112 00113 if (mode_==Platform_Network::ConnectionMode_TCP) 00114 { 00115 hints.ai_socktype = SOCK_STREAM; // Socket type that provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. 00116 hints.ai_protocol = IPPROTO_TCP; // Use Transmission Control Protocol (TCP). 00117 } 00118 else if (mode_==Platform_Network::ConnectionMode_UDP) 00119 { 00120 hints.ai_socktype = SOCK_DGRAM; // Socket type that supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. 00121 hints.ai_protocol = IPPROTO_UDP; // Use User Datagram Protocol (UDP). 00122 } 00123 00124 // Resolve the server address and port 00125 addrinfo* result = 0; 00126 char portString[256]; 00127 SNPrintF(portString,256,"%d",port_); // We need the port as a string 00128 int error=getaddrinfo(address_, portString, &hints, &result); 00129 if (error!=0) 00130 { 00131 const char* errorMsg=network_->GetErrorMessage(error); 00132 DebugPrint(("getaddrinfo FAILED: %d - %s\n",error,errorMsg)); 00133 return false; 00134 } 00135 00136 // Create the socket 00137 socket_ = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 00138 if (socket_==INVALID_SOCKET) 00139 { 00140 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00141 DebugPrint(("socket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00142 00143 freeaddrinfo(result); 00144 00145 DebugPrint(("FAILED creating socket!\n")); 00146 return false; 00147 } 00148 00149 // Set socket to nonblocking mode 00150 u_long nonblocking = 1; 00151 if (ioctlsocket(socket_, FIONBIO, &nonblocking)==SOCKET_ERROR) 00152 { 00153 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00154 DebugPrint(("ioctlsocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00155 00156 freeaddrinfo(result); 00157 if (closesocket(socket_)!=0) 00158 { 00159 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00160 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00161 } 00162 00163 socket_=INVALID_SOCKET; 00164 DebugPrint(("FAILED setting nonblocking mode on socket!\n")); 00165 return false; 00166 } 00167 00168 // Get maximum message size for this socket 00169 int optLen=sizeof(maxMessageSize_); 00170 if (getsockopt(socket_,SOL_SOCKET,SO_MAX_MSG_SIZE,reinterpret_cast<char*>(&maxMessageSize_),&optLen)==SOCKET_ERROR) 00171 { 00172 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00173 DebugPrint(("getsockopt FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00174 00175 freeaddrinfo(result); 00176 if (closesocket(socket_)!=0) 00177 { 00178 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00179 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00180 } 00181 00182 socket_=INVALID_SOCKET; 00183 DebugPrint(("FAILED retrieving maximum message size\n")); 00184 return false; 00185 } 00186 00187 // Connect to server 00188 if (connect(socket_, result->ai_addr, (int)result->ai_addrlen)==SOCKET_ERROR) 00189 { 00190 if (WSAGetLastError()!=WSAEWOULDBLOCK) 00191 { 00192 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00193 DebugPrint(("connect FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00194 00195 freeaddrinfo(result); 00196 00197 if (closesocket(socket_)!=0) 00198 { 00199 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00200 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00201 } 00202 00203 socket_=INVALID_SOCKET; 00204 DebugPrint(("FAILED connecting socket!\n")); 00205 return false; 00206 } 00207 waitingToConnect_=true; 00208 } 00209 else 00210 { 00211 connected_=true; 00212 } 00213 00214 freeaddrinfo(result); 00215 return true; 00216 } 00217 00218 00219 //*** Disconnect *** 00220 00221 bool Platform_Win32_Network_Client::Disconnect() 00222 { 00223 if (socket_!=INVALID_SOCKET) 00224 { 00225 closesocket(socket_); 00226 socket_=INVALID_SOCKET; 00227 } 00228 00229 return true; 00230 } 00231 00232 00233 //*** IsConnected *** 00234 00235 bool Platform_Win32_Network_Client::IsConnected() 00236 { 00237 return connected_; 00238 } 00239 00240 00241 //*** SendData *** 00242 00243 void Platform_Win32_Network_Client::SendData(const void* buffer, int size) 00244 { 00245 dataToSend_.Write(static_cast<const char*>(buffer),size); 00246 } 00247 00248 00249 //*** GetReceivedDataSize *** 00250 00251 int Platform_Win32_Network_Client::GetReceivedDataSize() 00252 { 00253 return receivedData_.GetSize(); 00254 } 00255 00256 00257 //*** GetReceivedData *** 00258 00259 void Platform_Win32_Network_Client::GetReceivedData(DynamicBuffer* buffer) 00260 { 00261 // Get data size 00262 int size=receivedData_.GetSize(); 00263 00264 // Copy data to callers buffer 00265 buffer->Write(static_cast<char*>(receivedData_.GetPointer()),size); 00266 00267 // Reset buffer 00268 receivedData_.Clear(false); 00269 } 00270 00271 00272 //*** Update *** 00273 00274 void Platform_Win32_Network_Client::Update() 00275 { 00276 // Detect connection established 00277 if (waitingToConnect_) 00278 { 00279 fd_set socketsToCheck; 00280 socketsToCheck.fd_count=1; 00281 socketsToCheck.fd_array[0]=socket_; 00282 00283 timeval timeout; 00284 timeout.tv_sec=0; 00285 timeout.tv_usec=0; 00286 00287 // Check if socket is ready for send 00288 if (select(0,0,&socketsToCheck,0,&timeout)==1) 00289 { 00290 // If it is, we're connected 00291 connected_=true; 00292 waitingToConnect_=false; 00293 } 00294 00295 } 00296 00297 // Send and receive data 00298 if (connected_) 00299 { 00300 timeval timeout; 00301 timeout.tv_sec=0; 00302 timeout.tv_usec=0; 00303 00304 fd_set socketsToCheck; 00305 00306 // Check if socket is ready for send, and we have data buffered for send 00307 socketsToCheck.fd_count=1; 00308 socketsToCheck.fd_array[0]=socket_; 00309 if (select(0,0,&socketsToCheck,0,&timeout)==1 && dataToSend_.GetSize()>0) 00310 { 00311 // Attempt to send all buffered data 00312 int dataSize=dataToSend_.GetSize(); 00313 int result=send(socket_,static_cast<char*>(dataToSend_.GetPointer()),Min(dataSize,1024*1024),0); 00314 00315 // On fail, we close the socket and mark the connection as lost 00316 if (result==SOCKET_ERROR) 00317 { 00318 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00319 DebugPrint(("senddata FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00320 00321 if (closesocket(socket_)!=0) 00322 { 00323 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00324 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00325 } 00326 socket_=INVALID_SOCKET; 00327 connected_=false; 00328 waitingToConnect_=false; 00329 DebugPrint(("FAILED sending data!\n")); 00330 return; 00331 } 00332 00333 // If we managed to send all buffered data, empty the send buffer 00334 if (dataSize==result) 00335 { 00336 dataToSend_.Clear(false); 00337 } 00338 else if (result>0) 00339 { 00340 // Remove the data that was successfully sent from the send buffer 00341 char* data=static_cast<char*>(dataToSend_.GetPointer()); 00342 MemCpy(data,data+result,dataSize-result); 00343 dataToSend_.SetPosition(dataSize-result); 00344 dataToSend_.SetSize(dataSize-result); 00345 } 00346 } 00347 00348 // Check if socket is ready for recv 00349 socketsToCheck.fd_count=1; 00350 socketsToCheck.fd_array[0]=socket_; 00351 if (select(0,&socketsToCheck,0,0,&timeout)==1) 00352 { 00353 char buffer[4096]; 00354 00355 // Receive data 00356 int size=recv(socket_,buffer,4096,0); 00357 if (size==SOCKET_ERROR) 00358 { 00359 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00360 DebugPrint(("recv FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00361 00362 if (closesocket(socket_)!=0) 00363 { 00364 const char* errorMsg=network_->GetErrorMessage(WSAGetLastError()); 00365 DebugPrint(("closesocket FAILED: %d - %s\n",WSAGetLastError(),errorMsg)); 00366 } 00367 00368 socket_=INVALID_SOCKET; 00369 connected_=false; 00370 waitingToConnect_=false; 00371 DebugPrint(("FAILED receiving data!\n")); 00372 } 00373 else if (size>0) 00374 { 00375 // Copy data to buffer 00376 receivedData_.Write(buffer,size); 00377 } 00378 } 00379 00380 } 00381 00382 }
Reproduction/republishing of any material on this site without permission is strictly prohibited.
