#include #ifdef WIN32 #pragma comment(lib,"WSOCK32.LIB") #include #include #include #include #include #elif LINUX #include #include #include #include #include #include #endif //WINDOWS #include "../../include/JSocket.h" #include "../../include/DebugRoutines.h" JSocket::JSocket(string ipAddr) : state(NOT_AVAILABLE), mfd(-1) { int result; struct hostent *hostentptr = 0; #ifdef WIN32 SOCKADDR_IN Adresse_Socket_Server; WORD wVersionRequested; WSADATA wsaData; wVersionRequested=MAKEWORD(1, 1); result = WSAStartup(wVersionRequested,&wsaData); if (result != 0) { DebugTrace("WSAStartup\t"); return; } #elif LINUX struct sockaddr_in Adresse_Socket_Server; #endif mfd = socket(AF_INET, SOCK_STREAM, 0); if(mfd < 0) return; DebugTrace("Connecting " << ipAddr); #ifdef WIN32 unsigned int addr_dest = inet_addr(ipAddr.c_str()); hostentptr=gethostbyaddr((char*) &addr_dest, 4, AF_INET); #elif LINUX hostentptr = gethostbyname(ipAddr.c_str()); #endif if (hostentptr == NULL) { DebugTrace("ERROR, no such host\n"); return; } #ifdef WIN32 ZeroMemory( (char*)&Adresse_Socket_Server, sizeof(Adresse_Socket_Server)); #elif LINUX bzero( (char*)&Adresse_Socket_Server, sizeof(Adresse_Socket_Server)); #endif //WINDOWS Adresse_Socket_Server.sin_family = (*hostentptr).h_addrtype; Adresse_Socket_Server.sin_port = htons(SERVER_PORT); Adresse_Socket_Server.sin_addr = *((struct in_addr*)(*hostentptr).h_addr); result = connect( mfd, (const struct sockaddr*)&Adresse_Socket_Server, sizeof(Adresse_Socket_Server)); if (result != 0) { DebugTrace("client connect failed :" << strerror(errno)); state = FATAL_ERROR; return; } state = CONNECTED; } bool JSocket::SetNonBlocking(int sock) { #ifdef WIN32 #elif LINUX int opts = fcntl(sock,F_GETFL); if (opts < 0) { perror("fcntl(F_GETFL)"); return false; } opts = (opts | O_NONBLOCK); if (fcntl(sock,F_SETFL,opts) < 0) { perror("fcntl(F_SETFL)"); return false; } #endif //WINDOWS return true; } JSocket::JSocket() : state(NOT_AVAILABLE), mfd(-1) { int result; #ifdef WIN32 SOCKADDR_IN Adresse_Socket_Connection; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(1,1); result = WSAStartup(wVersionRequested,&wsaData); if (result != 0) { DebugTrace("WSAStartup\t"); return; } #elif LINUX struct sockaddr_in Adresse_Socket_Connection; #endif //WINDOWS mfd=socket( AF_INET, SOCK_STREAM,0); #ifdef WIN32 #elif LINUX int reuse_addr = 1; /* Used so we can re-bind to our port while a previous connection is still in TIME_WAIT state. */ /* So that we can re-bind to it without TIME_WAIT problems */ setsockopt(mfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); #endif //WINDOWS SetNonBlocking(mfd); #ifdef WIN32 ZeroMemory( &Adresse_Socket_Connection,sizeof(Adresse_Socket_Connection)); #elif LINUX bzero( &Adresse_Socket_Connection,sizeof(Adresse_Socket_Connection)); #endif //WINDOWS Adresse_Socket_Connection.sin_family = AF_INET; Adresse_Socket_Connection.sin_port = htons(SERVER_PORT); result = ::bind(mfd, (struct sockaddr*)&Adresse_Socket_Connection, sizeof(Adresse_Socket_Connection)); if (result != 0) { state = FATAL_ERROR; DebugTrace("bind error:" << strerror(errno)); return; } result = listen(mfd,1); if(result != 0) { state = FATAL_ERROR; DebugTrace("listen error:" << strerror(errno)); return; } state = DISCONNECTED; } JSocket::JSocket(int fd) : state(CONNECTED), mfd(fd) { } JSocket::~JSocket() { Disconnect(); #ifdef WIN32 WSACleanup(); #endif } void JSocket::Disconnect() { state = JSocket::DISCONNECTED; if(mfd) { #ifdef WIN32 closesocket(mfd); #elif LINUX close(mfd); #endif mfd = 0; } } JSocket* JSocket::Accept() { #ifdef WIN32 SOCKADDR_IN Adresse_Socket_Cliente; int Longueur_Adresse; #elif LINUX struct sockaddr_in Adresse_Socket_Cliente; socklen_t Longueur_Adresse; #endif //WINDOWS JSocket* socket = NULL; while (mfd) { fd_set set; FD_ZERO(&set); FD_SET(mfd, &set); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000 * 100; int result = select(mfd+1, &set, NULL, NULL, &tv); if (result > 0 && FD_ISSET(mfd, &set)) { Longueur_Adresse = sizeof(Adresse_Socket_Cliente); int val = accept( mfd, (struct sockaddr*)&Adresse_Socket_Cliente, &Longueur_Adresse); DebugTrace("connection on client port "<< ntohs(Adresse_Socket_Cliente.sin_port)); if (val >= 0) { state = CONNECTED; socket = new JSocket(val); } break; } } return socket; } int JSocket::Read(char* buff, int size) { if (state == CONNECTED) { fd_set set; FD_ZERO(&set); FD_SET(mfd, &set); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000 * 100; int result = select(mfd+1, &set, NULL, NULL, &tv); if (result > 0 && FD_ISSET(mfd, &set)) { #ifdef WIN32 int readbytes = recv(mfd, buff, size, 0); #elif LINUX int readbytes = read(mfd, buff, size); #endif //WINDOWS if(readbytes < 0) { #ifdef WIN32 DebugTrace("Error reading from socket: " << WSAGetLastError()); #endif //WINDOWS Disconnect(); return -1; } else if(readbytes == 0) { Disconnect(); return 0; } else return readbytes; } else if( result < 0) { return -1; } } return 0; } int JSocket::Write(char* buff, int size) { int size1 = size; while (size > 0 && state == CONNECTED) { fd_set set; FD_ZERO(&set); FD_SET(mfd, &set); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000 * 100; int result = select(mfd+1, NULL, &set, NULL, &tv); if( result > 0 && FD_ISSET(mfd, &set)) { int len = send(mfd, buff, size, 0); if (len < 0) { return -1; } size -= len; buff += len; } else if (result < 0) { Disconnect(); return -1; } } return size1 - size; }