Files
Sun1602/GameLogic/util/sockutil.cpp
T
2022-10-26 12:25:11 +08:00

1678 lines
36 KiB
C++

// SockUtil.cpp: implementation of the CSockUtil class.
//
//////////////////////////////////////////////////////////////////////
#include "../stdafx.h"
#include "SockUtil.h"
#include <WINSOCK.H>
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
//#include <sys/time.h>
#include <errno.h>
#include <sys/types.h>
//#include <sys/socket.h>
//#include <netinet/in.h>
//////////////////////////////////////////////////////////////////////
// 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<maxlen; n++)
{
if( (rc = recv(fd, &c, 1,0)) == 1 )
{
*ptr++ = c;
if( c == '\n' )
break;
}
else if( rc == 0 )
{
if( n == 1 )
return(0);
else
break;
}
else
return(-1);
}
*ptr = 0;
return(n);
}
//////////////////////////////////////////////////////////////////////////
int so_readline_timeout(SOCKET fd, char *ptr, int maxlen, int nTime)
{
int n;
int rc;
char c;
for(n=1; n<maxlen; n++)
{
if( so_select(fd, nTime) <= 0 )
{
if( n == 1)
return(-1);
else
return(n-1);
}
if( (rc = recv(fd, &c, 1, 0)) == 1 )
{
*ptr++ = c;
if( c == '\n' )
break;
}
else if( rc == 0 )
{
if( n == 1 )
return(0);
else
break;
}
else
return(-1);
}
*ptr = 0;
return(n);
}
//////////////////////////////////////////////////////////////////////////
int so_readn_timeout(SOCKET fd, char *ptrP, int nbytes, int nTime)
{
int nleft, nread;
nleft = nbytes;
while (nleft > 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;
}
*/