NBSocket

#ifndef _NBSOCKET_H_
#define _NBSOCKET_H_
 
#include<winsock2.h>
#include<string>
#include"Channel.h"
 
class NBSocket
{
public:
	NBSocket();
	~NBSocket();
 
	int Connectconst 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::Connectconst char * sIP, 
	short iPort, struct timeval * pTV )
{
	m_sIP = sIP;
	m_iPort = iPort;
	m_iSock = socket(AF_INETSOCK_STREAMIPPROTO_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_SOCKETSO_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, NULLNULL,  &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;
}
 
 
 
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值