// SockUtil.cpp: implementation of the CSockUtil class. // ////////////////////////////////////////////////////////////////////// #include "../stdafx.h" #include "SockUtil.h" #include #include #include //#include #include #include #include //#include #include #include //#include //#include ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// int so_init() { WORD wversionRequested; WSADATA wsadata; int err; wversionRequested = MAKEWORD( 2, 2 ); err = ::WSAStartup( wversionRequested, &wsadata ); if ( err != 0 ) { _LOG("WSAStartup Err"); return -1; } if ( LOBYTE( wsadata.wVersion ) != 2 || HIBYTE( wsadata.wVersion ) != 2 ) { _LOG("wVersion invalid"); return -1; } return 0; } int so_select(SOCKET sockFd, int nTime) { int ret; fd_set rfdSet; struct timeval timeout; FD_ZERO(&rfdSet); FD_SET(sockFd, &rfdSet); if (nTime > 0) { timeout.tv_sec = nTime; timeout.tv_usec = 0; ret = select(sockFd+1, &rfdSet, (fd_set *)0, (fd_set *)0, (struct timeval *)&timeout); } else { ret = select(sockFd+1, &rfdSet, (fd_set *)0, (fd_set *)0, (struct timeval *)NULL); } if( ret == 0 ) /* Timeout */ return(0); else if( ret < 0 ) return(-1); if( FD_ISSET(sockFd, &rfdSet) ) return(1); else return(-1); } ////////////////////////////////////////////////////////////////////////// int so_select_write(SOCKET sockFd, int nTime) { int ret; fd_set wfdSet; struct timeval timeout; FD_ZERO(&wfdSet); FD_SET(sockFd, &wfdSet); if (nTime > 0) { timeout.tv_sec = nTime; timeout.tv_usec = 0; ret = select(sockFd+1, (fd_set *)0, &wfdSet, (fd_set *)0, (struct timeval *)&timeout); } else { ret = select(sockFd+1, (fd_set *)0, &wfdSet, (fd_set *)0, (struct timeval *)NULL); } if( ret == 0 ) /* Timeout */ return(0); else if( ret < 0 ) return(-1); if( FD_ISSET(sockFd, &wfdSet) ) return(1); else return(-1); } ////////////////////////////////////////////////////////////////////////// int so_readn(SOCKET fd, char *ptrP, int nbytes) { int nleft, nread; nleft = nbytes; while (nleft > 0) { if ( (nread = recv(fd, ptrP, nleft,0)) <= 0) return(nread); nleft -= nread; ptrP += nread; } return(nbytes - nleft); } ////////////////////////////////////////////////////////////////////////// int so_readline(SOCKET fd, char *ptr, int maxlen) { int n; int rc; char c; for(n=1; n 0) { if( so_select(fd, nTime) <= 0 ) { if( nleft == nbytes ) return(-1); else return(nbytes - nleft); } if ( (nread = recv(fd, ptrP, nleft, 0)) <= 0) return(nread); nleft -= nread; ptrP += nread; } return(nbytes - nleft); } ////////////////////////////////////////////////////////////////////////// char* recv_message(SOCKET fd, int nTime) { char *pStr = NULL; uint16_t len; unsigned short size; if( so_select(fd, nTime) <= 0 ) return NULL; else if( recv(fd, (char*)&len, sizeof(uint16_t), 0) <= 0 ) return NULL; size = ntohs(len); pStr = (char *)calloc(size+1, sizeof(char)); if( so_readn_timeout(fd, pStr, size, nTime) != size ) { FREE_MEM(pStr); return NULL; } return pStr; } ////////////////////////////////////////////////////////////////////////// int send_message(SOCKET fd, char *res) { uint16_t len = htons(strlen(res)); if( send(fd, (char*)&len, sizeof(uint16_t), 0) <= 0 ) return(-1); return(so_writen(fd, res, strlen(res))); } ////////////////////////////////////////////////////////////////////////// int so_writen(SOCKET fd, char *ptrP, int nbytes) { int nleft, nwritten; int ntry = 0; nleft = nbytes; while (nleft > 0 && ntry < 5) { nwritten = send(fd, ptrP, nleft, 0); if (nwritten <= 0) { ntry++; if (nwritten == 0) continue; if (WSAGetLastError() == WSAEWOULDBLOCK ) continue; else return(-1); } nleft -= nwritten; ptrP += nwritten; } return(nbytes - nleft); } ////////////////////////////////////////////////////////////////////////// /*int getRandomPort(int start, int num) { _tzset(); int pidForRandom; struct timeval tp; // struct _timezone tz; if (num < 1) return(-1); if (num == 1) return(start); gettimeofday(&tp, &tz); pidForRandom = getpid(); return(start + ((tp.tv_sec + pidForRandom) % num)); return 0; } */ ////////////////////////////////////////////////////////////////////////// /* int connect_nonblock(SOCKET sockfd, const struct sockaddr *ptrSaddr, int nSaddrlen, int nTimes) { int n; int flags; int error; int len; fd_set rset; fd_set wset; struct timeval tval; // if( (flags = getsockopt(sockfd, F_GETFL, 0)) < 0 ) // { // // fcntl() error // } // // fcntl(sockfd, F_SETFL, flags|O_NONBLOCK); ULONG nonBlk = TRUE; ioctlsocket( sockfd, FIONBIO, &nonBlk ); error = 0; if( (n = connect(sockfd, (struct sockaddr *)ptrSaddr, nSaddrlen)) == -1 ) // if( n == 0 ) // goto DONE; // else if( _errno != WSAEINPROGRESS ) // return(-1); FD_ZERO(&rset); FD_SET(sockfd, &rset); wset = rset; tval.tv_sec = nTimes; tval.tv_usec = 0; if( (n = select(sockfd+1, &rset, &wset, NULL, nTimes ? &tval : NULL)) == 0 ) { error = WSAETIMEDOUT; goto DONE; } if( FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset) ) { len = sizeof(error); if( getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) == -1 ) { error = WSAETIMEDOUT; goto DONE; } } else { error = -1; goto DONE; } DONE: // if( fcntl(sockfd, F_SETFL, flags) < 0 ) // ; // fcntl() error ioctlsocket( sockfd, FIONBIO, &nonBlk ); if( error ) { closesocket(sockfd); _errno = error; return(-1); } return(0); } */ ////////////////////////////////////////////////////////////////////////// void* cioReceiveMessage(SOCKET& sockfd, int* Error, int* length) { // return ReceiveNetMessage(Error, length); int l; int TickCount = 0; *Error = 0; char* buf = new char[*length]; char* tempbuf = buf; int recl = 0; do { l = recv(sockfd, tempbuf, *length-recl, 0); if (l==SOCKET_ERROR || l==0) { *Error = 1; delete buf; return NULL; }; recl+=l; tempbuf+=l; if (recl<*length) { TickCount+=1; Sleep(50);//retry to receive every 10 miliseconds }; }while(recl<*length && TickCount<2000); *length = recl; return buf; } //########################################################################## u_long get_netaddr( const char* address ) { struct hostent* host; const char* ptr; /* First try it as aaa.bbb.ccc.ddd. */ for( ptr = address; *ptr && (isdigit(*ptr) || *ptr == '.'); ptr++ ); if( *ptr == 0 ) return( inet_addr( address ) ); if( (host = gethostbyname( address )) ) return( ((struct in_addr *)*host->h_addr_list)->s_addr ); return( INADDR_NONE ); } u_short get_netport( const char* service, const char* proto ) { const char* ptr; struct servent* serv; /* First try it as a number */ for( ptr = service; *ptr && isdigit(*ptr); ptr++ ); if( *ptr == 0 ) return( htons( (u_short)atoi( service ) ) ); /* Try to read it from services database */ if( (serv = getservbyname( service, proto )) ) return( serv->s_port ); return( (u_short)-1 ); } char* get_peer_addr( SOCKET sock, char* buf, size_t len ) { struct sockaddr_in addr; int addr_len; int result; addr_len = sizeof( addr ); result = getpeername( sock, (struct sockaddr FAR*)&addr, &addr_len ); if( result == SOCKET_ERROR ) return( NULL ); if( len > 0 ) { strncpy( buf, inet_ntoa( addr.sin_addr ), len - 1 ); buf[len - 1] = 0; } return( buf ); } char* get_peer_hostname( SOCKET sock, char* buf, size_t len ) { struct sockaddr_in addr; int addr_len; struct hostent* phe; int result; addr_len = sizeof( addr ); result = getpeername( sock, (struct sockaddr FAR*)&addr, &addr_len ); if( result == SOCKET_ERROR ) return( NULL ); phe = gethostbyaddr( (const char FAR*)&addr.sin_addr.s_addr, sizeof(addr.sin_addr.s_addr), addr.sin_family ); if( !phe ) return( NULL ); if( len > 0 ) { if( phe->h_name ) { strncpy( buf, phe->h_name, len - 1 ); buf[len - 1] = 0; } else { strncpy( buf, inet_ntoa( addr.sin_addr ), len - 1 ); } } return( buf ); } int get_peer_port( SOCKET sock ) { struct sockaddr_in addr; int addr_len; int result; int port; addr_len = sizeof( addr ); result = getpeername( sock, (struct sockaddr FAR*)&addr, &addr_len ); if( result == SOCKET_ERROR ) return( SOCKET_ERROR ); port = ntohs( addr.sin_port ); return( port ); } char* get_sock_addr( SOCKET sock, char* buf, size_t len ) { struct sockaddr_in addr; int addr_len; int result; addr_len = sizeof( addr ); result = getsockname( sock, (struct sockaddr FAR*)&addr, &addr_len ); if( result == SOCKET_ERROR ) return( NULL ); if( len > 0 ) { strncpy( buf, inet_ntoa( addr.sin_addr ), len - 1 ); buf[len - 1] = 0; } return( buf ); } char* get_sock_hostname( SOCKET sock, char* buf, size_t len ) { struct sockaddr_in addr; int addr_len; struct hostent* phe; int result; addr_len = sizeof( addr ); result = getsockname( sock, (struct sockaddr FAR*)&addr, &addr_len ); if( result == SOCKET_ERROR ) return( NULL ); phe = gethostbyaddr( (const char FAR*)&addr.sin_addr.s_addr, sizeof(addr.sin_addr.s_addr), addr.sin_family ); if( !phe ) return( NULL ); if( len > 0 ) { if( phe->h_name ) { strncpy( buf, phe->h_name, len - 1 ); buf[len - 1] = 0; } else { strncpy( buf, inet_ntoa( addr.sin_addr ), len - 1 ); } } return( buf ); } int get_sock_port( SOCKET sock ) { struct sockaddr_in addr; int addr_len; int result; int port; addr_len = sizeof( addr ); result = getsockname( sock, (struct sockaddr FAR*)&addr, &addr_len ); if( result == SOCKET_ERROR ) return( SOCKET_ERROR ); port = ntohs( addr.sin_port ); return( port ); } int set_nonblk_mode( SOCKET sock, u_long mode ) { return( ioctlsocket( sock, FIONBIO, &mode ) ); } SOCKET sock_accept( SOCKET listen_sock, int* p_timeout ) { int rs; if( p_timeout && (rs = sock_wait( listen_sock, *p_timeout, TRUE )) <= 0 ) { if( rs == 0 ) *p_timeout = -1; return( INVALID_SOCKET ); } return( accept( listen_sock, NULL, NULL ) ); } int sock_close( SOCKET sock ) { return( closesocket( sock ) ); } SOCKET sock_connect( const char* address, u_short port, int type, int* p_timeout ) { struct sockaddr_in addr; SOCKET connect_sock; ZeroMemory( (PVOID)&addr, sizeof(addr) ); addr.sin_family = AF_INET; addr.sin_port = htons( port ); if( (addr.sin_addr.s_addr = get_netaddr( address )) == INADDR_NONE ) return( INVALID_SOCKET ); if( (connect_sock = socket( AF_INET, type, 0 )) == INVALID_SOCKET ) return( INVALID_SOCKET ); if( type == SOCK_STREAM ) { if( p_timeout ) { fd_set fds_error; fd_set fds_write; int rs = -1; struct timeval tv; tv.tv_sec = *p_timeout; tv.tv_usec = 0; FD_ZERO( &fds_write ); FD_SET( connect_sock, &fds_write ); FD_ZERO( &fds_error ); FD_SET( connect_sock, &fds_error ); if( set_nonblk_mode( connect_sock, 1 ) || ( connect( connect_sock, (struct sockaddr *) &addr, sizeof(addr) ) == SOCKET_ERROR && ( (rs = select( 0, NULL, &fds_write, &fds_error, &tv )) <= 0 || !FD_ISSET( connect_sock, &fds_write ) ) ) || set_nonblk_mode( connect_sock, 0 ) ) { int last_error = WSAGetLastError(); closesocket( connect_sock ); if( rs == 0 ) *p_timeout = -1; WSASetLastError( last_error ); return( INVALID_SOCKET ); } } else if( connect( connect_sock, (struct sockaddr *) &addr, sizeof(addr) ) == SOCKET_ERROR ) { int last_error = WSAGetLastError(); closesocket( connect_sock ); WSASetLastError( last_error ); return( INVALID_SOCKET ); } return( connect_sock ); } /* Otherwise, must be for udp, so bind to address. */ if( bind( connect_sock, (struct sockaddr *) &addr, sizeof(addr) ) == SOCKET_ERROR ) { int last_error = WSAGetLastError(); closesocket( connect_sock ); WSASetLastError( last_error ); return( INVALID_SOCKET ); } return( connect_sock ); } int sock_init( LPWSADATA lpWSAData ) { WSADATA WSAData; if( !lpWSAData ) lpWSAData = &WSAData; return( WSAStartup( MAKEWORD(2,2), lpWSAData ) ); } SOCKET sock_listen( const char* address, u_short port, int type, int backlog ) { struct sockaddr_in addr; SOCKET listen_sock; int reuse_addr = 1; /* Setup internet address information. This is used with the bind() call */ ZeroMemory( (PVOID)&addr, sizeof(addr) ); addr.sin_family = AF_INET; addr.sin_port = htons( port ); if( address ) { if( (addr.sin_addr.s_addr = get_netaddr( address )) == INADDR_NONE ) return( INVALID_SOCKET ); } else { addr.sin_addr.s_addr = htonl(INADDR_ANY); } if( (listen_sock = socket( AF_INET, type, 0 )) == INVALID_SOCKET ) return( INVALID_SOCKET ); setsockopt( listen_sock, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse_addr, sizeof(reuse_addr) ); if( bind( listen_sock, (struct sockaddr *) &addr, sizeof(addr) ) == SOCKET_ERROR ) { int last_error = WSAGetLastError(); closesocket( listen_sock ); WSASetLastError( last_error ); return( INVALID_SOCKET ); } if( type == SOCK_STREAM && listen( listen_sock, backlog ) == SOCKET_ERROR ) { int last_error = WSAGetLastError(); closesocket( listen_sock ); WSASetLastError( last_error ); return( INVALID_SOCKET ); } return( listen_sock ); } int sock_read( SOCKET sock, char* buf, size_t count ) { int nleft, nread; nleft = count; while (nleft > 0) { if ( (nread = recv(sock, buf, nleft,0)) <= 0) return(nread); nleft -= nread; buf += nread; } return(count - nleft); /* size_t bytes_read = 0; int rs; if( stop_byte == -1 ) { if( p_timeout && (rs = sock_wait( sock, *p_timeout, TRUE )) <= 0 ) { if( rs == 0 ) *p_timeout = -1; return( SOCKET_ERROR ); } bytes_read = recv( sock, buf, count, 0 ); return( bytes_read >= 0 ? bytes_read : SOCKET_ERROR ); } else { int this_read; while( bytes_read < count ) { if( p_timeout && (rs = sock_wait( sock, *p_timeout, TRUE )) <= 0 ) { if( rs == 0 ) *p_timeout = -1; return( SOCKET_ERROR ); } this_read = recv( sock, buf, 1, 0 ); if( this_read == 0 ) return( bytes_read ); if( this_read == SOCKET_ERROR ) return( SOCKET_ERROR ); bytes_read++; if( *(buf++) == (char)stop_byte ) return( bytes_read ); } } return( count );*/ } int sock_send( SOCKET sock, const char *buf, size_t count ) { size_t bytes_sent = 0; // int rs; int this_send; while( bytes_sent < count ) { // if( p_timeout && (rs = sock_wait( sock, *p_timeout, FALSE )) <= 0 ) // { // if( rs == 0 ) *p_timeout = -1; // return( SOCKET_ERROR ); // } this_send = send( sock, buf, count - bytes_sent, 0 ); if( this_send == 0 ) return( bytes_sent ); if( this_send == SOCKET_ERROR ) return( SOCKET_ERROR ); bytes_sent += this_send; buf += this_send; } return( count ); } int sock_uninit() { return( WSACleanup() ); } int sock_wait( SOCKET sock, int timeout, int for_read ) { fd_set fds_test; int rstatus; struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; FD_ZERO( &fds_test ); FD_SET( sock, &fds_test ); if( for_read ) rstatus = select( 0, &fds_test, NULL, NULL, &tv ); else rstatus = select( 0, NULL, &fds_test, NULL, &tv ); if( rstatus == SOCKET_ERROR ) return( SOCKET_ERROR ); if( rstatus == 0 || !FD_ISSET( sock, &fds_test ) ) return( 0 ); return( 1 ); } int sock_read( SOCKET sock, char* buf, size_t count, int* p_timeout ) { int nleft, nread; int rs; nleft = count; while(nleft > 0) { if( p_timeout && (rs = sock_wait( sock, *p_timeout, TRUE )) <= 0 ) { if( rs == 0 ) *p_timeout = -1; return( SOCKET_ERROR ); } if ( (nread = recv(sock, buf, nleft,0)) <= 0) return(nread); nleft -= nread; buf += nread; } return(count - nleft); } int sock_send( SOCKET sock, const char *buf, size_t count, int* p_timeout ) { size_t bytes_sent = 0; int rs; int this_send; while( bytes_sent < count ) { if( p_timeout && (rs = sock_wait( sock, *p_timeout, FALSE )) <= 0 ) { if( rs == 0 ) *p_timeout = -1; return( SOCKET_ERROR ); } this_send = send( sock, buf, count - bytes_sent, 0 ); if( this_send == 0 ) return( bytes_sent ); if( this_send == SOCKET_ERROR ) return( SOCKET_ERROR ); bytes_sent += this_send; buf += this_send; } return( count ); } BOOL sendCommand(char* ip, USHORT port, int* p_timeout, const char* pSendBuffer, int nSendSize, char* pRecvBuffer, int nRecvSize ) { SOCKET hSocket = sock_connect(ip, port, SOCK_STREAM, p_timeout); if(INVALID_SOCKET == hSocket) return FALSE; if(SOCKET_ERROR == sock_send(hSocket, pSendBuffer, nSendSize, p_timeout) ) { sock_close(hSocket); return FALSE; } if( SOCKET_ERROR == sock_read(hSocket, pRecvBuffer, nRecvSize, p_timeout) ) { sock_close(hSocket); return FALSE; } sock_close(hSocket); return TRUE; } //#########################################################################################33 /* ////////////////////////////////////////////////////////////////////////// // nonBlock_connect, Block_SendRecv char* processIO_nbConnect_bSendRecv( const char* address, u_short port, int nTimeout, const char* szSendData, int& nError) { if(strlen(szSendData) <= 0) { // _LOG("No Data to send !"); nError = ERR_SENDDATA_SIZE; return NULL; } nError = ERR_UNKNOWN; //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // winsock startup if (0 != SockInit()) { nError = ERR_SOCK_STARTUP; return NULL; } ////////////////////////////////////////////////////////////////////////// char* pStr = NULL; int nByteLeft, nByteToRecv, nByteToSend, nByteSent, nByteRecved; uint16_t nByteOfData = 0; int result = -1; u_long option; //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // socket creation SOCKET client = ::socket(AF_INET, SOCK_STREAM,0); if (INVALID_SOCKET == client) { // _LOG("socket creation fail"); nError = ERR_SOCK_CREATION; goto DONE; } // change to nonBlock option = 1; result = ioctlsocket(client, FIONBIO, &option); if (SOCKET_ERROR == result) { // _LOG("ioctl fail : %d", ::GetLastError() ); nError = ERR_SOCK_IOCTL; goto DONE; } //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // connect struct timeval tv; tv.tv_sec = nTimeout; tv.tv_usec = 0; fd_set wfd, efd; // connect sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = inet_addr(address); // local machine address addr.sin_port = htons(port); result = ::connect(client, (sockaddr*)&addr, sizeof(sockaddr_in)); if (SOCKET_ERROR == result) { if (WSAEWOULDBLOCK != WSAGetLastError()) { nError = ERR_SOCK_CONNECT; goto DONE; } else { // wait for connet result FD_ZERO(&wfd); FD_ZERO(&efd); FD_SET(client, &wfd); FD_SET(client, &efd); // The select function returns the total number of socket handles that are ready and contained // in the fd_set structures, zero if the time limit expired, or // SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, // WSAGetLastError can be used to retrieve a specific error code. if( select(0, 0, &wfd, &efd, &tv) <= 0) // if (SOCKET_ERROR == result || 0 == rfd.fd_count) { // _LOG("connection fail"); nError = ERR_SOCK_CONNECT; goto DONE; } } } _LOG("connection established (%s:%d)", address, port); // // change to Blocking mode option = 0; result = ioctlsocket(client, FIONBIO, &option); //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // send //---------------------------------------------- // send nByteOfData nByteOfData = htons(strlen(szSendData)); result = ::send(client, (char*)&nByteOfData, sizeof(uint16_t), 0); if (SOCKET_ERROR == result) { // _LOG("send error : %d", ::WSAGetLastError() ); nError = ERR_SOCK_SEND; goto DONE; } _LOG("sent nByteOfData [%d]", result); //---------------------------------------------- // send Data nByteToSend = strlen(szSendData); nByteSent = 0; do { result = ::send(client, &szSendData[nByteSent], nByteToSend - nByteSent, 0); if (SOCKET_ERROR == result) { // _LOG("send error : %d", ::WSAGetLastError() ); nError = ERR_SOCK_SEND; goto DONE; } else { nByteSent += result; } } while(nByteSent != nByteToSend); // _LOG("sent Data [%d]", nByteSent); //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // recv //---------------------------------------------------------- // recv nByteOfData if( recv(client, (char*)&nByteOfData, sizeof(uint16_t), 0) <= 0 ) { // _LOG("recv error : %d", ::WSAGetLastError() ); nError = ERR_SOCK_RECV; FREE_MEM(pStr); goto DONE; } //---------------------------------------------------------- // recv Data nByteToRecv = ntohs(nByteOfData); if(nByteToRecv <= 0 || nByteToRecv > MAX_RECVDATA_LEN) { nError = ERR_RECVDATA_SIZE; goto DONE; } // _LOG("nByteToRecv (%d)", nByteOfData); pStr = (char *)calloc(nByteToRecv+1, sizeof(char)); nByteLeft = nByteToRecv; nByteRecved = 0; //-------------------------------------------- do { result = ::recv(client, &pStr[nByteRecved], nByteLeft, 0); if (result <= 0 ) { // _LOG("recv error : %d", ::WSAGetLastError() ); nError = ERR_SOCK_RECV; FREE_MEM(pStr); goto DONE; } else { nByteLeft -= result; nByteRecved += result; } } while(nByteLeft > 0); // _LOG(pStr); closesocket(client); ::WSACleanup(); return pStr; //------------------------------------------- DONE: if (INVALID_SOCKET != client) { closesocket(client); } ::WSACleanup(); return NULL; } ////////////////////////////////////////////////////////////////////////// // nonBlock_connect, SendRecv char* processIO_nbConnect_nbSendRecv( const char* address, u_short port, int nTimeout, const char* szSendData, int& nError) { if(strlen(szSendData) <= 0) { nError = ERR_SENDDATA_SIZE; return NULL; } nError = ERR_UNKNOWN; //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // winsock startup if (0 != SockInit()) { nError = ERR_SOCK_STARTUP; return NULL; } ////////////////////////////////////////////////////////////////////////// char* pStr = NULL; int nByteLeft, nByteToRecv, nByteToSend, nByteSent, nByteRecved; uint16_t nByteOfData = 0; int result = -1; u_long option; //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // socket creation SOCKET client = ::socket(AF_INET, SOCK_STREAM,0); if (INVALID_SOCKET == client) { nError = ERR_SOCK_CREATION; goto DONE; } // Release for reuse this port by another users or processes... // const int on = 1; // setsockopt(client, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); option = 1; result = ioctlsocket(client, FIONBIO, &option); if (SOCKET_ERROR == result) { nError = ERR_SOCK_IOCTL; goto DONE; } //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // connect struct timeval tv; tv.tv_sec = nTimeout; tv.tv_usec = 0; fd_set rfd, wfd, efd; // connect sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = inet_addr(address); // local machine address addr.sin_port = htons(port); result = ::connect(client, (sockaddr*)&addr, sizeof(sockaddr_in)); if (SOCKET_ERROR == result) { if (WSAEWOULDBLOCK != WSAGetLastError()) { nError = ERR_SOCK_CONNECT; goto DONE; } else { FD_ZERO(&wfd); FD_ZERO(&efd); FD_SET(client, &wfd); FD_SET(client, &efd); // The select function returns the total number of socket handles that are ready and contained // in the fd_set structures, zero if the time limit expired, or // SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, // WSAGetLastError can be used to retrieve a specific error code. if( (select(0, 0, &wfd, &efd, &tv) <= 0) || !FD_ISSET( client, &wfd ) ) // if (SOCKET_ERROR == result || result//0 == rfd.fd_count) { nError = ERR_SOCK_CONNECT; goto DONE; } } } // option = 0; // result = ioctlsocket(client, FIONBIO, &option); //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // send //---------------------------------------------- // send nByteOfData nByteOfData = htons(strlen(szSendData)); result = ::send(client, (char*)&nByteOfData, sizeof(uint16_t), 0); if (SOCKET_ERROR == result) { nError = ERR_SOCK_SEND; goto DONE; } //---------------------------------------------- // send Data nByteToSend = strlen(szSendData); nByteSent = 0; do { FD_ZERO( &wfd ); FD_SET( client, &wfd ); if( ( select( 0, NULL, &wfd, NULL, &tv ) <= 0) || !FD_ISSET(client, &wfd) ) { nError = ERR_SOCK_SEND; goto DONE; } result = ::send(client, &szSendData[nByteSent], nByteToSend - nByteSent, 0); if (SOCKET_ERROR == result) { nError = ERR_SOCK_SEND; goto DONE; } else { nByteSent += result; } } while(nByteSent != nByteToSend); //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // recv //---------------------------------------------------------- // recv nByteOfData FD_ZERO(&rfd); FD_SET(client, &rfd); if( (select(0, &rfd, 0, 0, &tv) == SOCKET_ERROR) || !FD_ISSET( client, &rfd ) ) { nError = ERR_SOCK_RECV; goto DONE; } if( recv(client, (char*)&nByteOfData, sizeof(uint16_t), 0) <= 0 ) { nError = ERR_SOCK_RECV; goto DONE; } //---------------------------------------------------------- // recv Data nByteToRecv = ntohs(nByteOfData); // _LOG("############### READ BYTESIZE : (%d)", nByteToRecv); if(nByteToRecv <= 0 || nByteToRecv > MAX_RECVDATA_LEN) { nError = ERR_RECVDATA_SIZE; goto DONE; } pStr = (char *)calloc(nByteToRecv+1, sizeof(char)); nByteLeft = nByteToRecv; nByteRecved = 0; //-------------------------------------------- do { FD_ZERO(&rfd); FD_SET(client, &rfd); if((select(0, &rfd, 0, 0, &tv) <= 0 ) || !FD_ISSET(client, &rfd) ) { nError = ERR_SOCK_RECV; FREE_MEM(pStr); goto DONE; } result = ::recv(client, &pStr[nByteRecved], nByteLeft, 0); if (result <= 0 ) { nError = ERR_SOCK_RECV; FREE_MEM(pStr); goto DONE; } else { nByteLeft -= result; nByteRecved += result; } // _LOG("############### READ ByteLeft : (%d)", nByteLeft); } while(nByteLeft > 0); // _LOG("############### READ DATA : (%s)", pStr); // _LOG("ByteSent(%d), ByteRecved(%d)", nByteSent, nByteToRecv); nError = ERR_SUCCESS; if (INVALID_SOCKET != client) { closesocket(client); } ::WSACleanup(); return pStr; //------------------------------------------- DONE: // _LOG("DONE : ############### READ DATA : (%s)", pStr); if (INVALID_SOCKET != client) closesocket(client); ::WSACleanup(); return NULL; } char* processNonBlockIO( const char* address, u_short port, int nTimeout, const char* szSendData, int& nError) { if(strlen(szSendData) <= 0) { nError = ERR_SENDDATA_SIZE; return NULL; } nError = ERR_UNKNOWN; //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // winsock startup if (0 != SockInit()) { nError = ERR_SOCK_STARTUP; return NULL; } ////////////////////////////////////////////////////////////////////////// char* pStr = NULL; int nByteLeft, nByteToRecv, nByteToSend, nByteSent, nByteRecved; uint16_t nByteOfData = 0; int result = -1; u_long option; //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // socket creation SOCKET client = ::socket(AF_INET, SOCK_STREAM,0); if (INVALID_SOCKET == client) { nError = ERR_SOCK_CREATION; goto DONE; } // Release for reuse this port by another users or processes... // const int on = 1; // setsockopt(client, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); option = 1; result = ioctlsocket(client, FIONBIO, &option); if (SOCKET_ERROR == result) { nError = ERR_SOCK_IOCTL; goto DONE; } //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // connect struct timeval tv; tv.tv_sec = nTimeout; tv.tv_usec = 0; fd_set rfd, wfd, efd; // connect sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = inet_addr(address); // local machine address addr.sin_port = htons(port); result = ::connect(client, (sockaddr*)&addr, sizeof(sockaddr_in)); if (SOCKET_ERROR == result) { if (WSAEWOULDBLOCK != WSAGetLastError()) { nError = ERR_SOCK_CONNECT; goto DONE; } else { FD_ZERO(&wfd); FD_ZERO(&efd); FD_SET(client, &wfd); FD_SET(client, &efd); // The select function returns the total number of socket handles that are ready and contained // in the fd_set structures, zero if the time limit expired, or // SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, // WSAGetLastError can be used to retrieve a specific error code. if( (select(0, 0, &wfd, &efd, &tv) <= 0) || !FD_ISSET( client, &wfd ) ) // if (SOCKET_ERROR == result || result//0 == rfd.fd_count) { nError = ERR_SOCK_CONNECT; goto DONE; } } } // option = 0; // result = ioctlsocket(client, FIONBIO, &option); //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // send //---------------------------------------------- // send nByteOfData // nByteOfData = htons(strlen(szSendData)); // result = ::send(client, (char*)&nByteOfData, sizeof(uint16_t), 0); // if (SOCKET_ERROR == result) // { // nError = ERR_SOCK_SEND; // goto DONE; // } //---------------------------------------------- // send Data nByteToSend = strlen(szSendData); nByteSent = 0; do { FD_ZERO( &wfd ); FD_SET( client, &wfd ); if( ( select( 0, NULL, &wfd, NULL, &tv ) <= 0) || !FD_ISSET(client, &wfd) ) { nError = ERR_SOCK_SEND; goto DONE; } result = ::send(client, &szSendData[nByteSent], nByteToSend - nByteSent, 0); if (SOCKET_ERROR == result) { nError = ERR_SOCK_SEND; goto DONE; } else { nByteSent += result; } } while(nByteSent != nByteToSend); //"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" // recv //---------------------------------------------------------- // recv nByteOfData FD_ZERO(&rfd); FD_SET(client, &rfd); if( (select(0, &rfd, 0, 0, &tv) == SOCKET_ERROR) || !FD_ISSET( client, &rfd ) ) { nError = ERR_SOCK_RECV; goto DONE; } if( recv(client, (char*)&nByteOfData, sizeof(uint16_t), 0) <= 0 ) { nError = ERR_SOCK_RECV; goto DONE; } //---------------------------------------------------------- // recv Data nByteToRecv = ntohs(nByteOfData); // _LOG("############### READ BYTESIZE : (%d)", nByteToRecv); if(nByteToRecv <= 0 || nByteToRecv > MAX_RECVDATA_LEN) { nError = ERR_RECVDATA_SIZE; goto DONE; } pStr = (char *)calloc(nByteToRecv+1, sizeof(char)); nByteLeft = nByteToRecv; nByteRecved = 0; //-------------------------------------------- do { FD_ZERO(&rfd); FD_SET(client, &rfd); if((select(0, &rfd, 0, 0, &tv) <= 0 ) || !FD_ISSET(client, &rfd) ) { nError = ERR_SOCK_RECV; FREE_MEM(pStr); goto DONE; } result = ::recv(client, &pStr[nByteRecved], nByteLeft, 0); if (result <= 0 ) { nError = ERR_SOCK_RECV; FREE_MEM(pStr); goto DONE; } else { nByteLeft -= result; nByteRecved += result; } // _LOG("############### READ ByteLeft : (%d)", nByteLeft); } while(nByteLeft > 0); // _LOG("############### READ DATA : (%s)", pStr); // _LOG("ByteSent(%d), ByteRecved(%d)", nByteSent, nByteToRecv); nError = ERR_SUCCESS; if (INVALID_SOCKET != client) { closesocket(client); } ::WSACleanup(); return pStr; //------------------------------------------- DONE: // _LOG("DONE : ############### READ DATA : (%s)", pStr); if (INVALID_SOCKET != client) closesocket(client); ::WSACleanup(); return NULL; } char* processIO_nbConnect_nbSendRecv_util( const char* address, u_short port, int nTimeout, const char* szSendData, int& nError) { nError = ERR_UNKNOWN; WSADATA wsd; SOCKET sClient; int ret = 0; struct sockaddr_in server; struct hostent *host = NULL; char* szRecvData = NULL; // Load Winsock // if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { _LOG("Failed to load Winsock library!"); ::WSACleanup(); nError = ERR_SOCK_STARTUP; return NULL; } // // Create the socket, and attempt to connect to the server // sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient == INVALID_SOCKET) { _LOG("socket() failed: %d", WSAGetLastError()); ::WSACleanup(); nError = ERR_SOCK_CREATION; return NULL; } // Release for reuse this port by another users or processes... // const int on = 1; // setsockopt(sClient, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = inet_addr(address); do { if (connect(sClient, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { _LOG("connect() failed: %d", WSAGetLastError()); nError = ERR_SOCK_CONNECT; break; } ////////////////////////////////////////////////////////////////////////// // Send data // ret = send_message(sClient, (char*)szSendData); if (ret < 1) { _LOG("send() failed: %d", WSAGetLastError()); nError = ERR_SOCK_SEND; break; } _LOG("SEND [%d bytes]: %s", ret, szSendData); ////////////////////////////////////////////////////////////////////////// // Recv data szRecvData = recv_message(sClient, nTimeout); if(!szRecvData) { _LOG("recv() failed: %d", WSAGetLastError()); nError = ERR_SOCK_RECV; break; } _LOG("RECV [%d bytes]: %s", strlen(szRecvData), szRecvData); closesocket(sClient); WSACleanup(); nError = ERR_SUCCESS; return szRecvData; } while(FALSE); if (INVALID_SOCKET != sClient) closesocket(sClient); ::WSACleanup(); return NULL; } */