void Socket::setBlockingMode(bool isBlocking) { #ifndef _WIN32 DB(PrintStatus(fd)); if (!_myIsConnected) { AC_WARNING << "Socket::setBlockingMode setting blocking mode of a not connected socket, the mode will be lost after you connect"; } int status = fcntl(fd, F_GETFL, 0); if (!isBlocking) { status |= O_NONBLOCK; } else { status &= ~O_NONBLOCK; } if (fcntl(fd, F_SETFL, status)== -1) { throw SocketError(getLastSocketError(), "Socket::setBlockingMode failed"); } #else u_long theFlag = 1; if (isBlocking) { theFlag = 0; } int theRC = ioctlsocket(fd, FIONBIO, &theFlag); if (theRC == SOCKET_ERROR) { int err = getLastSocketError(); throw SocketError(err, "Socket::setBlockingMode failed"); } #endif }
unsigned Socket::receive(void *data, const unsigned maxlen) { if(_myTimeOut) { struct timeval tv; fd_set readset; FD_ZERO(&readset); #if defined(_MSC_VER) #pragma warning(push,1) #endif //defined(_MSC_VER) FD_SET(fd, &readset); #if defined(_MSC_VER) #pragma warning(pop) #endif //defined(_MSC_VER) // Initialize time out struct tv.tv_sec = getConnectionTimeout(); tv.tv_usec = 0; int result = select(fd + 1, &readset, NULL, NULL, &tv); if (result <= 0){ int err = getLastSocketError(); throw SocketError(err, std::string( "disconnect or timeout while receiveing from socket " + hostname(getRemoteAddress()) + ":" + as_string(getRemotePort()))); } } int bytesread = recv(fd, (char*)data, maxlen, 0); if (bytesread>0){ return bytesread; } else if (bytesread == 0) { _myIsConnected = false; // XXX: hack for tcp disconnect //throw SocketDisconnected(PLUS_FILE_LINE); } else { int err = getLastSocketError(); if(err == OS_SOCKET_ERROR(EWOULDBLOCK)) { return 0; } else { throw SocketError(err, "receive() failed"); } } return 0; }
unsigned Socket::send(const void *data, unsigned len) { int byteswritten; if ((byteswritten=::send(fd, (char*)data, len, getSendFlags())) != static_cast<int>(len)) { int err = getLastSocketError(); throw SocketError(err, "Socket::send() failed."); } return byteswritten; }
void terminateSockets() { #ifdef _WIN32 AC_DEBUG << "Calling WSACleanup()."; if ( WSACleanup() != 0 ) { int err = getLastSocketError(); throw SocketError(err, "inet::terminateSockets()"); } #endif }
int ftpSend(socket_t s, const void *data, int len) { int currLen = 0; do { #if defined(__APPLE__) && defined(SO_NOSIGPIPE) currLen = send(s, data, len, SO_NOSIGPIPE); #elif defined(MSG_NOSIGNAL) currLen = send(s, data, len, MSG_NOSIGNAL); #else currLen = send(s, data, len, 0); #endif if(currLen >= 0) { if(currLen == 0) { int errorNumber = getLastSocketError(); const char *errText = getLastSocketErrorText(&errorNumber); if(VERBOSE_MODE_ENABLED) printf("\nERROR #1 ftpExecute ERROR ON SEND for socket = %d, data len = %d, error = %d [%s]\n",s,len,errorNumber,errText); } len -= currLen; data = (uint8_t*)data + currLen; } else { int errorNumber = getLastSocketError(); const char *errText = getLastSocketErrorText(&errorNumber); if(VERBOSE_MODE_ENABLED) printf("\nERROR #2 ftpExecute ERROR ON SEND for socket = %d, data len = %d, currLen = %d, error = %d [%s]\n",s,len,currLen,errorNumber,errText); return -1; } } while(len > 0); return 0; }
int Socket::peek(int n) { int rc; #ifndef _WIN32 // XXX: This is inefficient. Use blocking calls instead. int status; char* buf; buf=new char[n]; status = fcntl(fd, F_GETFL, 0); if (!(status & FNONBLOCK)) { fcntl(fd,F_SETFL,status | FNONBLOCK); } rc = recvfrom(fd,buf,n,MSG_PEEK,NULL,NULL); if (rc == -1) { if (errno == EAGAIN) { // this is OK rc = 0; } else { delete[] buf; throw SocketError(getLastSocketError(), "Socket::peek() failed."); } } if (!(status & FNONBLOCK)) { fcntl(fd,F_SETFL,status); } delete[] buf; return rc; #else //TODO: Bug #564 u_long theBytesInBuffer; rc = ioctlsocket(fd, FIONREAD, &theBytesInBuffer); if (rc == SOCKET_ERROR) { int err = getLastSocketError(); throw SocketError(err, "Socket::peek() failed."); } return min(theBytesInBuffer, static_cast<u_long>(n)); // For compatibility with the linux version. #endif }
void Socket::close() { if (isValid()) { #ifdef _WIN32 int rc = closesocket(fd); if (rc == SOCKET_ERROR) { int err = getLastSocketError(); throw SocketError(err, "Socket::close() failed."); } #else // TODO: error handling. ::close(fd); #endif fd = -1; AC_DEBUG << "Socket closed" << endl; } }
int main( int argc, char* argv[] ) { if ( argc != 4 ) { std::cout << "error parameters. usage: " << argv[0] << " ip port packetnum"; return -1; } Log::init(); int packetnum = atoi( argv[3] ); if ( packetnum < 0 ) { packetnum = 100; } socketstartup(); SOCKET clientfd = tcp_client( argv[1], argv[2] ); if ( !isvalidsock( clientfd ) ) { Log::trace( "cannot connect server" ); return -1; } char recvbuf[MAX_BUF_SIZE]; int sendcount = 0; int recvcount = 0; int recverrorcount = 0; for ( ;; ) { int recvn = recv( clientfd, recvbuf, sizeof( recvbuf ), 0 ); if ( sizeof( recvbuf ) == recvn ) { bool brecvwrite = true; for ( int i = 0; i < sizeof( recvbuf ); ++i ) { if ( recvbuf[i] != 'A' ) { brecvwrite = false; break; } } if ( brecvwrite ) { #ifdef H_OS_WINDOWS static DWORD tmLastRecvMsg = 0; DWORD tnow = GetTickCount(); double fdiff = (double)( tnow - tmLastRecvMsg ) / 1000.0f; if ( fdiff > 2.0 ) { std::ostringstream log; log << "recv a message from server, but it is too long, interval:" << fdiff << "s."; Log::error( log.str() ); } else { Log::trace( "recv a message from server." ); } tmLastRecvMsg = tnow; #else Log::trace( "recv a message from server." ); #endif recvcount++; } else { Log::trace( "recv message, but the content is wrong." ); recverrorcount++; } } else { static int errorcount = 0; if ( 10 == errorcount++ ) { break; } } if ( recvcount == packetnum ) { memset( recvbuf, 'q', sizeof(recvbuf) ); } int sendn = 0; do { sendn = send( clientfd, recvbuf, sizeof( recvbuf ), 0 ); if ( -1 == sendn ) { static int errorcount = 0; if ( 10 == errorcount++ ) { break; } std::cout << "send error. errno=" << getLastSocketError(); msleep( 100 ); } else { //Log::trace( " send a message to client." ); sendcount++; break; } } while ( -1 == sendn ); if ( recvcount == packetnum ) { std::ostringstream log; log << "==========================================================="; log << "\n\tRecv count=" << recvcount << "\n\tSend count=" << sendcount << "\n\tRecv error count=" << recverrorcount; log << "\n==========================================================="; Log::trace( log.str() ); CLOSE_SOCKET( clientfd ); break; } } // end of send-recv for(;;) return 0; }
const char * getLastSocketErrorText(int *errNumber) { int errId = (errNumber != NULL ? *errNumber : getLastSocketError()); return strerror(errId); }
int main( int argc, char* argv[] ) { if ( argc != 4 ) { std::cout << "error parameters. usage: " << argv[0] << " ip port packetinteval"; return -1; } Log::init(); float packetinteval = atof( argv[3] ); if ( packetinteval <= 0.001 ) { packetinteval = 0.5; } socketstartup(); SOCKET serversockfd = tcp_server( argv[1], argv[2] ); int myerrno = getLastSocketError(); if ( ! isvalidsock( serversockfd ) ) { std::cout << "create tcp server error. errno=" << myerrno << std::endl; msleep( packetinteval * 1000 );// 1/10 of packetinteval*1000 return -1; } char recvbuf[MAX_BUF_SIZE]; char msgbuf[MAX_BUF_SIZE]; memset( msgbuf, 'A', sizeof( msgbuf ) ); for ( ;; ) { Log::trace( "OK, tcp server is running, and waiting for client connection." ); struct sockaddr_in clientaddr; socklen_t addrlen = sizeof( clientaddr ); memset( &clientaddr, 0, addrlen ); SOCKET clientfd = accept( serversockfd, (struct sockaddr*)&clientaddr, &addrlen ); int myerrno = getLastSocketError(); if ( ! isvalidsock( clientfd ) ) { std::cout << "accept error. errno=" << myerrno << std::endl; msleep( packetinteval * 1000 );// 1/10 of packetinteval*1000 continue; } int sendcount = 0; int recvcount = 0; int recverrorcount = 0; for ( ;; ) { int sendn = send( clientfd, msgbuf, sizeof( msgbuf ), 0 ); int myerrno = getLastSocketError(); if ( -1 == sendn ) { static int errorcount = 0; if ( 10 == errorcount++ ) { break; } std::cout << "send error. errno=" << myerrno; msleep( packetinteval * 1000 );// 1/10 of packetinteval*1000 continue; } Log::trace( "send a message to client." ); sendcount++; int recvn = recv( clientfd, recvbuf, sizeof(msgbuf), 0 ); if ( sizeof(msgbuf) == recvn ) { bool brecvwrite = true; for ( int i = 0; i < sizeof(msgbuf); ++i ) { if ( recvbuf[i] != 'A' && recvbuf[i] != 'q' && recvbuf[i] != 'Q' ) { brecvwrite = false; break; } } if ( brecvwrite ) { Log::trace( "recv a message from client." ); recvcount++; } else { Log::trace( "recv message content is wrong." ); recverrorcount++; } } else { static int errorcount = 0; if ( 10 == errorcount++ ) { Log::trace( "recv message error." ); break; } } if ( recvbuf[0] == 'q' || recvbuf[0] == 'Q' ) { std::ostringstream log; log << "==========================================================="; log << "\n\tRecv count=" << recvcount << "\n\tSend count=" << sendcount << "\n\tRecv error count=" << recverrorcount; log << "\n==========================================================="; Log::trace( log.str() ); CLOSE_SOCKET( clientfd ); break; } msleep( (unsigned int)(packetinteval * 1000) ); } // end of send-recv for(;;) }//end of accept loop for(;;) CLOSE_SOCKET( serversockfd ); return 0; }