#ifndef _NBSOCKET_H_ #define _NBSOCKET_H_ #include<winsock2.h> #include<string> #include"Channel.h" class NBSocket { public: NBSocket(); ~NBSocket(); int Connect( const char * sIP, short iPort, struct timeval * pTV = NULL ); int Send( char * pBuffer, int iLen ); int Recv( ); void SetChannel( Channel * pChannel ) { m_pChannel = pChannel; } private: SOCKET m_iSock; Channel * m_pChannel; std::string m_sIP; int m_iPort; }; #endif
#include "stdafx.h" #include "NBSocket.h" #include "util.hpp" #include <iostream> using namespace std; NBSocket::NBSocket() : m_iSock(INVALID_SOCKET),m_pChannel(NULL) { } NBSocket::~NBSocket() { if ( m_iSock != INVALID_SOCKET ) { closesocket( m_iSock ); } } int NBSocket::Connect( const char * sIP, short iPort, struct timeval * pTV ) { m_sIP = sIP; m_iPort = iPort; m_iSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ( m_iSock == INVALID_SOCKET ) { cout<< __FUNCTION__<<":Create Socket Failed::"<<GetLastError()<<endl; return -1; } unsigned long on = 1; SetNonBlock( m_iSock, on ); struct sockaddr_in ServerAddr; ServerAddr.sin_family = AF_INET; ServerAddr.sin_addr.s_addr = inet_addr( sIP); ServerAddr.sin_port = htons( iPort ); memset(ServerAddr.sin_zero, 0x00, 8); int iRet = connect( m_iSock, (SOCKADDR*)&ServerAddr, sizeof(SOCKADDR)); if ( iRet == 0 ) { return 0; } else if ( iRet == -1 && errno != EINPROGRESS ) { fd_set Readset; FD_ZERO(&Readset); FD_SET(m_iSock, &Readset); iRet = select( -1, NULL, &Readset, NULL, pTV ); if ( iRet < 0 ) { cout<< __FUNCTION__<<":select Failed:"<<GetLastError()<<endl; return -2; } else if ( iRet == 0 ) { // timeout cout<< __FUNCTION__<<": connect timeout :"<<GetLastError() << ".sIP:" << sIP << ",iPort:" << iPort <<endl; return -2; } else { int error = -1; int optLen = sizeof(int); getsockopt( m_iSock, SOL_SOCKET, SO_ERROR, (char*)&error, &optLen); if ( 0 != error ) { cout<< __FUNCTION__<<":get socket error:"<<GetLastError()<<endl; return -3; } char on = 1; SetNoDelay( m_iSock, on ); linger stLinger; stLinger.l_onoff = 1; stLinger.l_linger = 0; SetLinger( m_iSock, stLinger ); } } else { return -1; } return 0; } int NBSocket::Send( char * pBuffer, int iLen ) { if ( m_iSock == - 1 ) { cout << __FUNCTION__ << ":m_iSock is invalid.reconnect:" << m_sIP << ":" << m_iPort << endl; int iRet = Connect( m_sIP.c_str(), m_iPort ); if ( iRet != 0 ) { return -1; } } struct timeval stTV; stTV.tv_sec = 3; stTV.tv_usec = 0; int iTotalSend = 0; while ( true ) { fd_set WriteSet; FD_ZERO(&WriteSet); FD_SET(m_iSock, &WriteSet); int iRet = select( -1, NULL, &WriteSet, NULL, &stTV ); if ( iRet <= 0 ) { cout<< __FUNCTION__ << ":select Failed:"<<GetLastError()<<endl; return -1; } else if ( iRet == 0 ) { cout<< __FUNCTION__ << ": send timeout :"<<GetLastError()<<endl; return -1; } else if ( FD_ISSET( m_iSock, &WriteSet ) ) { int iCurSend = send( m_iSock, pBuffer + iTotalSend, iLen - iTotalSend, 0 ); if ( iCurSend == -1 ) { int iError = GetLastError(); if ( iError == WSAEWOULDBLOCK ) { continue; } else { cout << __FUNCTION__<< ":send failed:" << iError << endl; closesocket( m_iSock ); m_iSock = -1; return -2; } } else { iTotalSend += iCurSend; if ( iTotalSend == iLen ) { break; } } } } return iTotalSend; } int NBSocket::Recv() { if ( m_iSock == - 1 ) { cout << __FUNCTION__ << ":m_iSock is invalid. reconnect " << m_sIP << ":" << m_iPort<< endl; int iRet = Connect( m_sIP.c_str(), m_iPort ); if ( iRet != 0 ) { return -1; } } string sRecvBuffer; int iBufferLen = 16384; sRecvBuffer.reserve( iBufferLen ); char pBuffer[16384]; struct timeval stTV; stTV.tv_sec = 10; stTV.tv_usec = 0; while ( true ) { fd_set ReadSet; FD_ZERO(&ReadSet); FD_SET(m_iSock, &ReadSet); int iRet = select( -1, &ReadSet, NULL, NULL, &stTV ); if ( iRet < 0 ) { cout<< __FUNCTION__ << ":select Failed:"<<GetLastError()<<endl; return -1; } else if ( iRet == 0 ) { //cout<< __FUNCTION__ << ": recv timeout :"<<GetLastError()<<endl; return 0; } else if ( FD_ISSET( m_iSock, &ReadSet ) ) { // recv 一直到EWOULDBLOCK while ( true ) { int iCurRecv = recv( m_iSock, pBuffer, iBufferLen, 0 ); //cout << "recv return :" << iCurRecv << endl; if ( iCurRecv == -1 ) { //cout << __FUNCTION__<< ":recv got error:" << GetLastError() << endl; int iError = GetLastError(); if ( iError == WSAEWOULDBLOCK ) { break; } else { cout << __FUNCTION__<< ":recv failed:" << iError << endl; closesocket( m_iSock ); m_iSock = -1; return -2; } } else if ( iCurRecv > 0 ) { sRecvBuffer.append( pBuffer, iCurRecv ); } else { cout << "recv return 0, server has close this socket, just return " << endl; closesocket( m_iSock ); m_iSock = -1; return -3; } } if ( !sRecvBuffer.empty() ) { m_pChannel->ProcessStream( sRecvBuffer.data(), sRecvBuffer.length() ); sRecvBuffer.clear(); return 0; } } } return -1; }
NBSocket
最新推荐文章于 2023-11-23 17:02:56 发布