ServerSocket.cpp
资源名称:1731.rar [点击查看]
上传用户:swkcbjrc
上传日期:2016-04-02
资源大小:45277k
文件大小:8k
源码类别:
游戏
开发平台:
Visual C++
- #include "StdAfx.h"
- #include "serversocket.h"
- #include "process.h"
- #define DATA_BUFSIZE 4096
- // 监听线程
- UINT ServerListenThread(LPVOID lParam)
- {
- LOGMESSAGE("服务器端监听中.....n");
- CServerSocket* pServer = (CServerSocket*)lParam;
- SOCKADDR_IN ClientAddr; // 定义一个客户端得地址结构作为参数
- int addr_length=sizeof(ClientAddr);
- while(TRUE)
- {
- if(pServer->dwEventTotal>=WSA_MAXIMUM_WAIT_EVENTS) // 因为超出了Windows的最大等待事件数量
- {
- LOGMESSAGE("已达到最大连接数!");
- continue;
- }
- SOCKET sockTemp = WSAAccept(pServer->sockListen,(SOCKADDR*)&ClientAddr,&addr_length, NULL, 0);
- if(sockTemp == INVALID_SOCKET)
- {
- LOGMESSAGE("Accept Connection failed!");
- continue;
- }
- pServer->nSockIndex = pServer->GetEmptySocket(); // 从Socket数组中获得一个空闲的socket
- pServer->sockAcceptArray[pServer->nSockIndex] = sockTemp;
- // 这里可以取得客户端的IP和端口,但是我们只取其中的SOCKET编号
- LPCTSTR lpIP = inet_ntoa(ClientAddr.sin_addr);
- UINT nPort = ClientAddr.sin_port;
- char strSock[80];
- sprintf(strSock,"New Client,SOCKET编号:%drn",pServer->sockAcceptArray[pServer->nSockIndex] );
- LOGMESSAGE(strSock);
- // 接收客户端连接以后,为每一个连入的SOCKET都初始化建立一个重叠结构
- pServer->Flags = 0;
- pServer->EventArray[pServer->nSockIndex] = WSACreateEvent();
- ZeroMemory(&pServer->AcceptOverlapped[pServer->nSockIndex],sizeof(WSAOVERLAPPED));
- char buffer[DATA_BUFSIZE];
- ZeroMemory(buffer,DATA_BUFSIZE);
- pServer->AcceptOverlapped[pServer->nSockIndex].hEvent = pServer->EventArray[pServer->nSockIndex]; // 关联事件
- pServer->DataBuf[pServer->nSockIndex].len = DATA_BUFSIZE;
- pServer->DataBuf[pServer->nSockIndex].buf = buffer;
- // 投递第一个WSARecv请求,以便开始在套接字上接受数据
- if(WSARecv(pServer->sockAcceptArray[pServer->nSockIndex] ,&pServer->DataBuf[pServer->nSockIndex],1,&pServer->dwRecvBytes,&pServer->Flags,
- & pServer->AcceptOverlapped[pServer->nSockIndex] ,NULL) == SOCKET_ERROR)
- {
- if(WSAGetLastError() != WSA_IO_PENDING)
- {
- // 返回WSA_IO_PENDING是正常情况,表示IO操作正在进行,不能立即完成
- // 如果不是WSA_IO_PENDING错误,就表示操作失败了
- LOGMESSAGE("错误:第一次投递Recv操作失败!!此套接字将被关闭!");
- closesocket(pServer->sockAcceptArray[pServer->nSockIndex]);
- pServer->sockAcceptArray[pServer->nSockIndex] = INVALID_SOCKET;
- WSACloseEvent(pServer->EventArray[pServer->nSockIndex]);
- continue;
- }
- }
- pServer->dwEventTotal ++;
- }
- return 0;
- }
- // 重叠I/O处理线程
- UINT OverlappedThread(LPVOID lParam)
- {
- CServerSocket* pServer = (CServerSocket*)lParam;
- while(pServer->bOverlapped) // 循环检测事件数组中的事件,并对接收的数据进行处理:)
- {
- DWORD dwIndex;
- // 等候重叠I/O调用结束
- // 因为我们把事件和Overlapped绑定在一起,重叠操作完成后我们会接到事件通知
- dwIndex = WSAWaitForMultipleEvents(pServer->dwEventTotal,pServer->EventArray,FALSE,INFINITE,FALSE);
- if(dwIndex == WSA_WAIT_TIMEOUT)
- continue;
- if(dwIndex == WSA_WAIT_FAILED) // 出现监听错误
- {
- Sleep(200);
- continue;
- }
- // 取得索引值,得知事件的索引号
- dwIndex = dwIndex - WSA_WAIT_EVENT_0;
- // 获得索引号以后,这个事件已经没有利用价值,重置之
- WSAResetEvent(pServer->EventArray[dwIndex]);
- // 然后确定当前索引号的SOCKET的重叠请求状态
- DWORD dwBytesTransferred;
- WSAOVERLAPPED& CurrentOverlapped = pServer->AcceptOverlapped[dwIndex]; // 这里纯粹为了减少代码长度,付给了一个临时变量
- SOCKET& sockCurrent = pServer->sockAcceptArray[dwIndex] ; // 同上
- WSAGetOverlappedResult(sockCurrent,&CurrentOverlapped ,
- &dwBytesTransferred,FALSE,&pServer->Flags);
- // 先检查通信对方是否已经关闭连接
- // 如果==0则表示连接已经,则关闭套接字
- if(dwBytesTransferred == 0)
- {
- char strSock[80];
- sprintf(strSock,"Client disconnect:SOCKET编号:%drn",pServer->sockAcceptArray[dwIndex] );
- LOGMESSAGE(strSock);
- closesocket(sockCurrent);
- sockCurrent = INVALID_SOCKET;
- //WSACloseEvent( EventArray[dwIndex] );
- pServer->dwEventTotal--;
- continue;
- }
- // DataBuf中包含接收到的数据,我们发到对话框中给予显示
- char strSock[80];
- sprintf(strSock,"Socket data SOCKET编号:%d,%srn",sockCurrent,pServer->DataBuf[dwIndex].buf);
- LOGMESSAGE(strSock);
- // 然后在套接字上投递另一个WSARecv请求(不要晕,注意看,代码和前面第一次WSARecv一样^_^)
- pServer->Flags = 0;
- ZeroMemory(&CurrentOverlapped,sizeof(WSAOVERLAPPED));
- char buffer[DATA_BUFSIZE];
- ZeroMemory(buffer,DATA_BUFSIZE);
- CurrentOverlapped.hEvent = pServer->EventArray[dwIndex];
- pServer->DataBuf[dwIndex].len = DATA_BUFSIZE;
- pServer->DataBuf[dwIndex].buf = buffer;
- // 开始另外一个WSARecv
- if(WSARecv(sockCurrent,&pServer->DataBuf[dwIndex],1,&pServer->dwRecvBytes,&pServer->Flags,
- &CurrentOverlapped ,NULL) == SOCKET_ERROR)
- {
- if(WSAGetLastError() != WSA_IO_PENDING)
- {
- LOGMESSAGE("错误:投递Recv操作失败!!此套接字将被关闭!");
- closesocket(sockCurrent);
- sockCurrent = INVALID_SOCKET;
- WSACloseEvent(pServer->EventArray[dwIndex]);
- pServer->dwEventTotal--;
- continue;
- }
- }
- }
- return 0;
- }
- CServerSocket::CServerSocket(void)
- {
- for(int i=0;i<WSA_MAXIMUM_WAIT_EVENTS;i++) // 初始化SOCKET
- {
- sockAcceptArray[i] = INVALID_SOCKET;
- }
- dwEventTotal=0;
- dwRecvBytes=0;
- Flags=0;
- nSockIndex = 0;
- bOverlapped = FALSE;
- }
- CServerSocket::~CServerSocket(void)
- {
- LOGMESSAGE("CServerSocket 析构!");
- WSACleanup();
- }
- int CServerSocket::InitWSASocket()
- {
- //init socket
- WSADATA WSD;
- WORD wVersionRequired = MAKEWORD( 2,2 );
- ZeroMemory(&WSD,sizeof(WSADATA));
- int nErrorNo = WSAStartup(wVersionRequired, &WSD);
- return nErrorNo;
- }
- // 这些都是固定套路了,没有区别
- int CServerSocket::StartListening(const UINT& port)
- {
- m_nPort = port;
- int nRet;
- InitWSASocket();
- sockListen = WSASocket(AF_INET,SOCK_STREAM,0, NULL, 0,WSA_FLAG_OVERLAPPED); //创建服务套接字(流式)
- //server_socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,WSA_FLAG_OVERLAPPED);
- SOCKADDR_IN ServerAddr; //分配端口及协议族并绑定
- ServerAddr.sin_family=AF_INET;
- ServerAddr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);
- ServerAddr.sin_port=htons(port);
- nRet=bind(sockListen,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr)); // 绑定套接字
- if(nRet==SOCKET_ERROR)
- {
- LOGMESSAGE("Bind Socket Fail!");
- closesocket(sockListen);
- return -1;
- }
- nRet=listen(sockListen,5); //开始监听,并设置监听客户端数量
- if(nRet==SOCKET_ERROR)
- {
- LOGMESSAGE("Listening Fail!");
- return -1;
- }
- StartupAcceptThread();
- StartupWorkThread();
- bOverlapped = TRUE;
- return 0;
- }
- int CServerSocket::StopListening()
- {
- bOverlapped = FALSE;
- return 0;
- }
- // 返回一个空闲的SOCKET,
- int CServerSocket::GetEmptySocket()
- {
- for(int i=0;i<WSA_MAXIMUM_WAIT_EVENTS;i++)
- {
- if(sockAcceptArray[i]==INVALID_SOCKET)
- {
- return i;
- }
- }
- return -1;
- }
- bool CServerSocket::StartupAcceptThread()
- {
- HANDLE hAcceptThread;
- DWORD dwThreadId;
- hAcceptThread = (HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)ServerListenThread,
- (LPVOID)this,0,(PBEGINTHREADEX_THREADID)&dwThreadId);
- if(hAcceptThread==NULL)
- {
- return false;
- }
- else
- {
- m_hAcceptThread=hAcceptThread;
- return true;
- }
- }
- bool CServerSocket::StartupWorkThread()
- {
- HANDLE hThread;
- DWORD dwThreadId;
- //启动服务器工作线程
- hThread = (HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)OverlappedThread,
- (LPVOID)this,0,(PBEGINTHREADEX_THREADID)&dwThreadId);
- if(hThread==NULL)
- {
- return false;
- }
- else
- m_hWorkThread=hThread;
- return true;
- }