00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef _WIN32
00024 #define EADDRINUSE WSAEADDRINUSE
00025 #include <winsock2.h>
00026 #else
00027 #include <netdb.h>
00028 #include <unistd.h>
00029 #include <netinet/tcp.h>
00030 #include <iostream>
00031 #endif
00032
00033 #include "SocketTCP.hh"
00034 #include "PrettyDebug.hh"
00035
00036 #include <cassert>
00037 #include <cerrno>
00038 #include <cstdlib>
00039 #include <cstring>
00040
00041 using std::cout ;
00042 using std::endl ;
00043
00044 namespace certi {
00045
00046 static pdCDebug D("SOCKTCP", "(SocketTCP) - ");
00047 static PrettyDebug G("GENDOC",__FILE__);
00048
00049 #ifdef _WIN32
00050 int SocketTCP::winsockInits = 0;
00051
00052 bool SocketTCP::winsockStartup()
00053 {
00054 WORD wVersionRequested;
00055 WSADATA wsaData;
00056 int lError;
00057
00058 if (winsockInits > 0)
00059 {
00060 winsockInits++;
00061 return true;
00062 }
00063 else if (winsockInits <0)
00064 {
00065 return false;
00066 }
00067
00068 wVersionRequested = MAKEWORD( 2, 0 );
00069 lError = WSAStartup( wVersionRequested, &wsaData );
00070 if (lError != 0)
00071 {
00072 winsockInits = -1;
00073 return false;
00074 }
00075
00076 if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0)
00077 {
00078 WSACleanup( );
00079 winsockInits = -1;
00080 return false;
00081 }
00082
00083 winsockInits = 1;
00084 return true;
00085 }
00086
00087 void SocketTCP::winsockShutdown()
00088 {
00089 winsockInits--;
00090 if (winsockInits==0)
00091 WSACleanup( );
00092 }
00093 #endif
00094
00095
00096 SocketTCP::SocketTCP()
00097 {
00098 _est_init_tcp = false ;
00099
00100 SentBytesCount = 0 ;
00101 RcvdBytesCount = 0 ;
00102
00103 #ifdef _WIN32
00104 winsockStartup();
00105 #endif
00106
00107 #ifdef SOCKTCP_BUFFER_LENGTH
00108 RBLength = 0 ;
00109 #endif
00110 }
00111
00112
00113 SocketTCP::~SocketTCP()
00114 {
00115 if (_est_init_tcp)
00116 close();
00117
00118 #ifdef _WIN32
00119 winsockShutdown();
00120 #endif
00121
00122 #ifdef RTI_PRINTS_STATISTICS
00123 cout << " TCP Socket " ;
00124 cout.width(2);
00125 cout << _socket_tcp << " : total = " ;
00126 cout.width(9);
00127 cout << SentBytesCount << "b sent " << endl ;
00128 cout << " TCP Socket " ;
00129 cout.width(2);
00130 cout << _socket_tcp << " : total = " ;
00131 cout.width(9);
00132 cout << RcvdBytesCount << "b received" << endl ;
00133 #endif
00134 }
00135
00136
00137 int SocketTCP::connect(in_port_t port, in_addr_t addr)
00138 {
00139 int Result ;
00140 struct protoent *TCPent ;
00141 int optval = 1 ;
00142
00143 assert(!_est_init_tcp);
00144
00145 _sockIn.sin_family=AF_INET ;
00146 _sockIn.sin_port=htons(port);
00147 _sockIn.sin_addr.s_addr=addr ;
00148
00149
00150 Result = ::connect(_socket_tcp, (sockaddr*)&_sockIn, sizeof(_sockIn));
00151
00152 if (Result < 0)
00153 return 0 ;
00154
00155
00156
00157 TCPent = getprotobyname("tcp");
00158 if (TCPent == NULL)
00159 {
00160 cout << "Unable to retrieve TCP protocol number." << endl ;
00161 return 0 ;
00162 }
00163
00164 if (setsockopt(_socket_tcp,
00165 TCPent->p_proto,
00166 TCP_NODELAY,
00167 (char *) &optval,
00168 sizeof(optval)))
00169 {
00170 cout << "Error while calling setsockopt." << endl ;
00171 return 0 ;
00172 }
00173
00174 if (Result < 0)
00175 return 0 ;
00176 else
00177 return 1 ;
00178 }
00179
00180
00181 int SocketTCP::accept(SocketTCP *serveur) throw (NetworkError)
00182 {
00183 std::stringstream msg;
00184 struct protoent *TCPent ;
00185 int optval = 1 ;
00186
00187 #ifdef _WIN32
00188 int l;
00189 #else
00190 socklen_t l;
00191 #endif
00192
00193 assert(!_est_init_tcp);
00194 assert(serveur != NULL);
00195
00196 l = sizeof(_sockIn);
00197
00198 _socket_tcp = ::accept(serveur->_socket_tcp, (sockaddr*)&_sockIn, &l);
00199 if (_socket_tcp < 0)
00200 {
00201 msg << "SocketTCP: Accept Failed"
00202 << "<" << strerror(errno) <<">";
00203 throw NetworkError(msg.str().c_str());
00204 }
00205
00206
00207 TCPent = getprotobyname("tcp");
00208 if (TCPent == NULL)
00209 {
00210 cout << "Unable to retrieve TCP protocol number." << endl ;
00211 return 0 ;
00212 }
00213
00214 if (setsockopt(_socket_tcp,
00215 TCPent->p_proto,
00216 TCP_NODELAY,
00217 (char *) &optval,
00218 sizeof(optval)))
00219 {
00220 cout << "Error while calling setsockopt." << endl ;
00221 return 0 ;
00222 }
00223
00224 _est_init_tcp = true ;
00225
00226 return 1 ;
00227 }
00228
00229
00230 int
00231 SocketTCP::bind(in_port_t port, in_addr_t addr)
00232 {
00233 long Length, Result ;
00234
00235 assert(!_est_init_tcp);
00236
00237 memset(&_sockIn, 0, sizeof(_sockIn));
00238
00239 _sockIn.sin_family = AF_INET ;
00240 _sockIn.sin_addr.s_addr = addr ;
00241 _sockIn.sin_port = htons(port);
00242
00243 Length = sizeof(_sockIn);
00244
00245 int on = 1 ;
00246
00247
00248 if (setsockopt(_socket_tcp,
00249 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)))
00250 perror("setsockopt");
00251
00252 Result = ::bind(_socket_tcp, (sockaddr *)&_sockIn, Length);
00253
00254 if (Result != 0) {
00255 perror("bind");
00256 return 0;
00257 }
00258 else
00259 return 1;
00260 }
00261
00262
00263 void
00264 SocketTCP::createConnection(const char *server_name, unsigned int port)
00265 throw (NetworkError)
00266 {
00267 std::stringstream msg;
00268
00269
00270 struct hostent *hptr = gethostbyname(server_name);
00271 if (NULL == hptr)
00272 {
00273 msg << "gethostbyname gave NULL answer for hostname <"
00274 << server_name
00275 << "> with error <"
00276 << strerror(errno)
00277 << ">";
00278 throw NetworkError(msg.str().c_str());
00279 }
00280
00281 in_addr_t addr = 0;
00282 memcpy((void *) &addr, (void *) hptr->h_addr, hptr->h_length);
00283
00284 createTCPClient(port, addr);
00285 }
00286
00287
00288 void
00289 SocketTCP::createTCPClient(in_port_t port, in_addr_t addr)
00290 throw (NetworkError)
00291 {
00292 assert(!_est_init_tcp);
00293 std::stringstream msg;
00294 if (!open())
00295 {
00296 msg << "Cannot open port <" << port
00297 << "> on addr <" << addr2string(addr)
00298 << "> : error =" << strerror(errno);
00299 throw NetworkError(msg.str().c_str());
00300 }
00301
00302 if (!connect(port, addr))
00303 {
00304 msg << "Cannot connect port <" << port
00305 << "> on addr <" << addr2string(addr)
00306 << "> : error =" << strerror(errno);
00307 throw NetworkError(msg.str().c_str());
00308 }
00309
00310 _est_init_tcp = true ;
00311 }
00312
00313
00314 void
00315 SocketTCP::createTCPServer(in_port_t port, in_addr_t addr)
00316 throw (NetworkError)
00317 {
00318 std::stringstream msg;
00319 assert(!_est_init_tcp);
00320
00321
00322 if (!open())
00323 {
00324 msg << "Cannot open port <" << port
00325 << "> on addr <" << addr2string(addr)
00326 << "> : error =" << strerror(errno);
00327 throw NetworkError(msg.str().c_str());
00328 }
00329
00330 if (!bind(port, addr))
00331 {
00332 msg << "Cannot bind port <" << port
00333 << "> on addr <" << addr2string(addr)
00334 << "> : error =" << strerror(errno);
00335 throw NetworkError(msg.str().c_str());
00336 }
00337
00338 if (!listen(MAX_BACKLOG))
00339 {
00340 msg << "Cannot listen port <" << port
00341 << "> on addr <" << addr2string(addr)
00342 << "> : error =" << strerror(errno);
00343 throw NetworkError(msg.str().c_str());
00344 }
00345
00346 _est_init_tcp = true ;
00347 }
00348
00349
00350
00351 void
00352 SocketTCP::send(const unsigned char *buffer, size_t size)
00353 throw (NetworkError, NetworkSignal)
00354 {
00355 long total_sent = 0 ;
00356 long expected_size = size ;
00357
00358 assert(_est_init_tcp);
00359
00360 D.Out(pdDebug, "Beginning to send TCP message...");
00361
00362 while (total_sent < expected_size)
00363 {
00364 #ifdef _WIN32
00365 int sent = ::send(_socket_tcp, (char*) buffer + total_sent, expected_size - total_sent, 0);
00366 #else
00367 int sent = ::send(_socket_tcp, buffer + total_sent, expected_size - total_sent, 0);
00368 #endif
00369
00370 if (sent < 0)
00371 {
00372 D.Out(pdExcept, "Error while sending on TCP socket.");
00373
00374 #ifdef _WIN32
00375 if(WSAGetLastError() == WSAEINTR)
00376 #else
00377 if(errno == EINTR)
00378 #endif
00379 throw NetworkSignal("");
00380 else
00381 {
00382 perror("TCP Socket(EmettreTCP) ");
00383 throw NetworkError("Error while sending TCP message.");
00384 }
00385 }
00386
00387 if (sent == 0)
00388 {
00389 D.Out(pdExcept, "No data could be sent, connection closed?.");
00390 throw NetworkError("Could not send any data on TCP socket.");
00391 }
00392
00393 total_sent += sent ;
00394 D.Out(pdTrace, "Sent %ld bytes out of %ld.", total_sent, expected_size);
00395 }
00396
00397 SentBytesCount += total_sent ;
00398 }
00399
00400
00401 void
00402 SocketTCP::close()
00403 {
00404 if (_est_init_tcp)
00405 {
00406 #ifdef _WIN32
00407 ::closesocket(_socket_tcp);
00408 #else
00409 ::close(_socket_tcp);
00410 #endif
00411 _est_init_tcp = false ;
00412 }
00413 }
00414
00415
00416 int
00417 SocketTCP::listen(unsigned long howMuch)
00418 {
00419 assert(!_est_init_tcp);
00420
00421 return ::listen(_socket_tcp, howMuch) >= 0 ;
00422 }
00423
00424
00425 in_addr_t
00426 SocketTCP::getAddr() const
00427 {
00428 return(_sockIn.sin_addr.s_addr);
00429 }
00430
00431
00432 in_port_t
00433 SocketTCP::getPort() const
00434 {
00435 return _sockIn.sin_port ;
00436 }
00437
00438
00442 bool
00443 SocketTCP::isDataReady() const
00444 {
00445 #ifdef SOCKTCP_BUFFER_LENGTH
00446 return RBLength > 0 ;
00447 #else
00448 return false ;
00449 #endif
00450 }
00451
00452
00453 int
00454 SocketTCP::open()
00455 {
00456 #ifdef _WIN32
00457 assert(winsockInits>0);
00458 #endif
00459 return(((_socket_tcp=socket(AF_INET,SOCK_STREAM,0))<0)?0:1);
00460 }
00461
00462
00463 SocketTCP &
00464 SocketTCP::operator=(SocketTCP &theSocket)
00465 {
00466 _sockIn.sin_addr.s_addr=theSocket.getAddr();
00467 _sockIn.sin_port =theSocket.getPort();
00468 _socket_tcp =theSocket.returnSocket();
00469
00470 return(*this);
00471 }
00472
00473
00474 void
00475 SocketTCP::receive(void *buffer, unsigned long size)
00476 throw (NetworkError, NetworkSignal)
00477 {
00478
00479 assert(_est_init_tcp);
00480
00481 long nReceived = 0 ;
00482 #ifndef SOCKTCP_BUFFER_LENGTH
00483 unsigned long RBLength = 0 ;
00484 #endif
00485
00486 D.Out(pdDebug, "Beginning to receive TCP message...(Size %ld)",size);
00487
00488 while (RBLength < size)
00489 {
00490
00491 #ifdef SOCKTCP_BUFFER_LENGTH
00492 nReceived = recv(_socket_tcp,
00493 ReadBuffer + RBLength,
00494 SOCKTCP_BUFFER_LENGTH - RBLength,
00495 0);
00496 #else
00497 nReceived = recv(_socket_tcp,
00498 (char *) buffer + RBLength,
00499 size - RBLength,
00500 0);
00501 #endif
00502
00503 if (nReceived < 0)
00504 {
00505 D.Out(pdExcept, "Error while receiving on TCP socket.");
00506 #ifdef _WIN32
00507 if(WSAGetLastError() == WSAEINTR)
00508 #else
00509 if(errno == EINTR)
00510 #endif
00511 throw NetworkSignal("");
00512 else
00513 {
00514 perror("TCP Socket(RecevoirTCP) ");
00515 throw NetworkError("Error while receiving TCP message.");
00516 }
00517 }
00518
00519 if (nReceived == 0)
00520 {
00521 D.Out(pdExcept, "TCP connection has been closed by peer.");
00522 throw NetworkError("Connection closed by client.");
00523 }
00524
00525 RBLength += nReceived ;
00526 RcvdBytesCount += nReceived ;
00527 }
00528 D.Out(pdTrace, "Received %ld bytes out of %ld.", RBLength, size);
00529
00530 #ifdef SOCKTCP_BUFFER_LENGTH
00531 memcpy(buffer, (void *) ReadBuffer, size);
00532 memmove((void *) ReadBuffer, (void *)(ReadBuffer + size), RBLength - size);
00533 RBLength -= size ;
00534 #endif
00535
00536 }
00537
00538
00539 unsigned long
00540 SocketTCP::returnAdress() const
00541 {
00542 return getAddr();
00543 }
00544
00545
00546 #ifdef _WIN32
00547 SOCKET SocketTCP::returnSocket() { return _socket_tcp ;}
00548 #else
00549 int SocketTCP::returnSocket() { return _socket_tcp ;}
00550 #endif
00551
00552
00554 void SocketTCP::setPort(in_port_t port)
00555 {
00556 _sockIn.sin_port=port ;
00557 }
00558
00559
00567 int
00568 SocketTCP::timeoutTCP(int sec, int usec)
00569 {
00570 assert(_est_init_tcp);
00571
00572 struct timeval time_out ;
00573 time_out.tv_sec = sec ;
00574 time_out.tv_usec = usec ;
00575
00576 fd_set fdset ;
00577 FD_ZERO(&fdset);
00578 FD_SET(_socket_tcp, &fdset);
00579
00580 int nb = select(_socket_tcp+1, &fdset, NULL, NULL, &time_out);
00581
00582 if (nb < 0)
00583 {
00584 #ifdef _WIN32
00585 if(WSAGetLastError() == WSAEINTR)
00586 #else
00587 if(errno == EINTR)
00588 #endif
00589 throw NetworkSignal("TCP::TimeOut signal interrupt.");
00590 else
00591 throw NetworkError("Select gave negative return value");
00592 }
00593 else
00594 return nb > 0 ;
00595 }
00596
00597 }
00598
00599