C++网络编程服务器select模型(参考)

#include
#include
#include
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
const int nPort=10000;
const int buf_len=1024;
struct Connection{
  SOCKET hSocket;
  char Buffer[buf_len];
  int nBytes;
  Connection(SOCKET socket):hSocket(socket),nBytes(0)//结构体构造函数,hSocket的初始值为socket,nBytes的初始值为0;
  {}
};  //注意:要加分号
typedef vector ConnectionList;
SOCKET BindListen()
{
	SOCKET HSListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建套接字
	sockaddr_in sdListen;
	sdListen.sin_family=AF_INET;
	sdListen.sin_port=htons(nPort);
	sdListen.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(HSListen,(sockaddr*)&sdListen,sizeof(sockaddr_in))==SOCKET_ERROR)
	{
		cout<<"绑定失败"<nByteshSocket,&fdRead);
		}
		//客户连接的缓冲区还有数据需要发送,就需要把其对应的套接字句柄放入到fdWrite中
		if(pConn->nBytes>0)
		{
			FD_SET(pConn->hSocket,&fdWrite);
		}
		//每个连接的套接字句柄都需要放到fd_Except中,以便select 能够检测其I/O错误
		FD_SET(pConn->hSocket,&fdExcept);
	}
}
//检查是否有新的客户连接
int CheckAccept(const fd_set &fdRead,const fd_set &fdExcept,SOCKET sdListen,ConnectionList &conns)
{
	int lastErr=0;
	//首先检查是否发生错误
	if(FD_ISSET(sdListen,&fdExcept))
	{
		int errlen=sizeof(lastErr);
		getsockopt(sdListen,SOL_SOCKET,SO_ERROR,(char *)&lastErr,&errlen);
		cout<<"I/O error"<=FD_SETSIZE-1)
		{
			return 0;
		}
		//调用accept来接受连接请求
		sockaddr_in saRemote;
		int nSize=sizeof(sockaddr_in);
		SOCKET sd=accept(sdListen,(sockaddr *)&saRemote,&nSize);
		lastErr=WSAGetLastError();
		//为了程序的健壮性,检查WSAEWOULDBLOCK错误
		if(sd==INVALID_SOCKET&&lastErr!=WSAEWOULDBLOCK)
		{
			cout<<"接收错误"<0)
	{
		//使用阻塞I/O模型把剩余数据发送出去
		u_long nNoBlock=0;
		if(ioctlsocket(sd,FIONBIO,&nNoBlock)==SOCKET_ERROR)
		{
			cout<<"ioctlsocket error"<0)
			{
				nSent+=nTemp;
			}
			else if(nTemp==SOCKET_ERROR)
			{cout<<"发送失败"<buffer+pConn->nBytes表示缓冲区Buffer可用空间的开始位置
	//buf_len-pConn->nBytes表示缓冲区Buffer可用空间的大小
	int nRet=recv(pConn->hSocket ,pConn->Buffer+pConn->nBytes,buf_len-pConn->nBytes,0);
	if(nRet>0)
	{
		pConn->nBytes+=nRet;
		return true;
	}
	//对方关闭了连接,调用被动安全关闭连接PassiveShutdown函数
	else if(nRet==0)
	{
		cout<<"对方关闭连接"<hSocket,pConn->Buffer,pConn->nBytes);
		return false;
	}
	//发生了错误。为了程序的健壮性,检查WSAEWOULDBLOCK错误
	else
	{
		int lastErr=WSAGetLastError();
		if(lastErr==WSAEWOULDBLOCK)
		{
			return true;
		}
		cout<<"接收失败"<hSocket,pConn->Buffer,pConn->nBytes,0);
	if(nSent>0)
	{
		pConn->nBytes-=nSent;
		//Buffer中还有数据尚未发送出去
		if(pConn->nBytes>0)
		{
			//把尚未发送的数据从Buffer的尾部移动到Buffer头部
			memmove(pConn->Buffer,pConn->Buffer+nSent,pConn->nBytes);
		}
		return true;
	}
	//对方关闭了连接,调用了被动安全关闭连接PassiveShutdown函数
	else if(nSent==0)
	{
		cout<<"对方关闭连接"<hSocket,pConn->Buffer,pConn->nBytes);
	    return false;
	}
	//发生了错误,为了程序的健壮性,检查WSAEWOULDBLOCK错误
	else
	{
		int lastErr=WSAGetLastError();
		if(lastErr==WSAEWOULDBLOCK)
		{
			return true;
		}
		cout<<"发送失败"<hSocket,&fdExcept))
		{
			bOk=false;
			int lastErr;
			int errlen=sizeof(lastErr);
			getsockopt(pConn->hSocket,SOL_SOCKET,SO_ERROR,(char*)&lastErr,&errlen);
			cout<<"I/O error"<hSocket,&fdRead))
			{
				bOk=TryRead(pConn);
			}
		}
		//发生了错误,关闭套接字并把其对应的Connection对象从conns中移除
		if(bOk==false)
		{
			closesocket(pConn->hSocket);
			delete pConn;
			it=conns.erase(it);
		}
		else
		{
			++it;
		}
	}
}
//select就绪通告I/O模型服务器的主体函数
void DoWork()
{
	//获取监听套接字
	SOCKET sdListen=BindListen();
	if(sdListen==INVALID_SOCKET)
	{}
	//定义conns,用于保存当前所有客户连接
	ConnectionList conns;
	//把监听套接字设为非阻塞模式
	u_long nNoBlock=1;
	if(ioctlsocket(sdListen,FIONBIO,&nNoBlock)==SOCKET_ERROR)
	{
		cout<<"ioctlsocket 错误"<hSocket);
		delete *it;
	}
	if(sdListen!=INVALID_SOCKET)
		closesocket(sdListen);
}
int main()
{
	WSAData wsaData;
	int nCode;
	if((nCode=WSAStartup(MAKEWORD(2,2),&wsaData))!=0)
	{
		cout<<"初始化失败"<

你可能感兴趣的:(C++,网络编程)