标签:校验码 tags private 列表 == nts 检测 server ldb
#pragma once #pragma warning(disable: 4786) #include "winsock2.h" #include <map> using namespace std; #define MAX_CONNECTION_NUMBER 2 // 最大连接数 typedef struct tagSvrSocket { int objectId; // 对象编号 int port; // Socket端口号 char ip[20]; // IP地址 bool bRegister; // 注册 bool bTrace; // 跟踪 SOCKET sock; // Socket tagSvrSocket() { objectId = 0; sock = NULL; port = 0; bRegister = false; bTrace = false; memset(ip, 0, sizeof(ip)); } } SvrSocket, *LPSvrSocket; typedef map<SOCKET, LPSvrSocket> MapSvrSocket,*LPMapSvrSocket; typedef MapSvrSocket::value_type vtSvrSocket; typedef MapSvrSocket::iterator itSvrSocket; class CServerSocket { public: CServerSocket(void); public: ~CServerSocket(void); public: SOCKET m_hSocket; // 监听socket 句柄 SOCKET m_hClientSocketLast; // 客户端最后一次连接的socket 句柄 sockaddr_in m_addr; // 每次客户端连接时,客户端的地址 UINT m_uPort; // 端口号 BOOL m_bInit; // 初始化winsock的信号 MapSvrSocket m_mapSvrSocket; // 客户端的winsock的map CRITICAL_SECTION m_CriticalSection; public: int InitAndListen(UINT nPort); virtual int CheckSocketReadable(SOCKET sock); virtual int CheckSocketWriteable(SOCKET sock); virtual int SendMsg(char *buff, USHORT len, SOCKET sock); virtual int ReceiveMsg(char* buff, SOCKET sock); virtual void CloseClientSocket(SOCKET sock); void GetSvrSockMap(MapSvrSocket & mapSevSocket); private: int InitSocket(); void GetError(DWORD error); };
#include "StdAfx.h" #include "ServerSocket.h" #define PACKHEAD_LEN 22 #define MAXDELAYTIME 2 // 最大延时2秒 #define MAX_LEN 1024 // 最大长度 CServerSocket::CServerSocket(void) { m_bInit = TRUE; m_hSocket = NULL; m_hClientSocketLast = NULL; m_uPort = 0; InitSocket(); InitializeCriticalSection(&m_CriticalSection); } CServerSocket::~CServerSocket(void) { for (itSvrSocket itsvrsock = m_mapSvrSocket.begin(); itsvrsock != m_mapSvrSocket.begin(); ++itsvrsock) { LPSvrSocket pSvrSocket = (LPSvrSocket)itsvrsock->second; CloseClientSocket(pSvrSocket->sock); } WSACleanup(); DeleteCriticalSection(&m_CriticalSection); } /* =========================================== 初始化 参数: 无 返回值: 0 成功. 1 失败,在返回1以前,显示错误原因。 *///========================================== int CServerSocket::InitSocket() { WSADATA wsaData; WORD version = MAKEWORD(2,2); int ret = WSAStartup(version, &wsaData); if (ret != 0) { TRACE("Initilize Error!\n"); m_bInit = FALSE; TRACE("socket 初始化错误\r\n"); } return ret; } /* ========================================== 服务侦听函数,绑定端口等待连接 参数: nPort:服务器端口号 返回值: 0 成功. -1 失败在返回1以前,显示错误原因。 *///========================================= int CServerSocket::InitAndListen(UINT nPort) { SOCKET tmpsock; if (!m_bInit) return -2; if (m_hSocket == NULL) { m_hSocket = socket(AF_INET, SOCK_STREAM, 0); ASSERT(m_hSocket != NULL); m_addr.sin_family = AF_INET; m_addr.sin_addr.S_un.S_addr = INADDR_ANY; m_addr.sin_port = htons(nPort); int ret = 0; int error = 0; // 绑定一个套接字到本机地址 ret = bind(m_hSocket, (LPSOCKADDR)&m_addr, sizeof(m_addr)); if (ret == SOCKET_ERROR) { closesocket(m_hSocket); m_hSocket = NULL; GetError(GetLastError()); return -1; } // 开始侦听过程,等待客户的连接 ret = listen(m_hSocket, 5); if (ret == SOCKET_ERROR) { closesocket(m_hSocket); m_hSocket = NULL; GetError(GetLastError()); return -1; } } SOCKADDR_IN saddr; int len = sizeof(saddr); tmpsock = accept(m_hSocket, (PSOCKADDR)&saddr, &len); if (tmpsock == INVALID_SOCKET) { GetError(GetLastError()); return -1; } CString strIP; strIP.Format(inet_ntoa(saddr.sin_addr)); // 连接数是否最大 EnterCriticalSection(&m_CriticalSection); if (m_mapSvrSocket.size() < MAX_CONNECTION_NUMBER) { // 保存最后一次连接成功的CDU的SOCKECT信息 m_hClientSocketLast = tmpsock; LPSvrSocket pSvrSocket = new SvrSocket; pSvrSocket->sock = tmpsock; pSvrSocket->port = saddr.sin_port; strcpy(pSvrSocket->ip, strIP); m_mapSvrSocket.insert(vtSvrSocket(tmpsock, pSvrSocket)); LeaveCriticalSection(&m_CriticalSection); } else { GetError(100); LeaveCriticalSection(&m_CriticalSection); return -3; } return 0; } /* ============== 函数功能:检测套接字是否可读 参数: 无 返回值: 0 可读 其他数值不可读 *///============= int CServerSocket::CheckSocketReadable(SOCKET sock) { fd_set fdset; struct timeval tv; tv.tv_sec=0; tv.tv_usec=1000; FD_ZERO(&fdset); FD_SET(sock,&fdset); int iRet = select(sock + 1, &fdset, NULL, NULL, &tv); if (iRet == 0) { return -1; } return 0; } /* ============== 函数功能:检测套接字是否可写 参数: 无 返回值: 0 可写 其他数值不可写 *///============= int CServerSocket::CheckSocketWriteable(SOCKET sock) { fd_set fdset; struct timeval tv; tv.tv_sec=0; tv.tv_usec=5000; FD_ZERO(&fdset); FD_SET(sock,&fdset); int iRet = select(sock + 1, NULL, &fdset, NULL, &tv); if (iRet == 0) { return -1; } return 0; } /* ==============
发送消息函数 参数: buff:发送的数据缓冲区。 返回值: 0 成功. -1 失败 *///============= int CServerSocket::SendMsg(char *buff, USHORT len, SOCKET sock) { ASSERT(buff != NULL); if (!m_bInit) return -1; int end = send(sock, buff, len, 0); if (end == SOCKET_ERROR) { GetError(GetLastError()); return -1; } return end; } /* ============== 接收发来的消息 参数: buff: 接收到的数据,即填满实参内存,实参需要是一个已经分配内存的缓冲区. whichSocket: 表示哪一个套接字开始接收,对应于m_SvrSocketBody的下标。 返回值: ret 成功,数据包长度. 负数 失败,在返回以前,显示错误原因。 *///============= int CServerSocket::ReceiveMsg(char* buff, SOCKET sock) { ASSERT(buff != NULL); if (!m_bInit) return -4; int iTotal = 0; int iRet = 0; time_t startTime = time(NULL); while (1) {// 收取包头标志4A 79 iRet = recv(sock, buff+iTotal, 1, 0); if (iRet <= 0) { return -1; } if (*(char*)buff == 0x4A) { iTotal = 1; iRet = recv(sock, buff+iTotal, 1, 0); if (iRet <= 0) { return -1; } if (*(char*)(buff+1) == 0x79) { iTotal = 2; break; } } iTotal = 0; if (time(NULL) - startTime > MAXDELAYTIME) { // printf("接收报头文超时\n"); return -2; } } iRet = recv(sock, buff+iTotal, PACKHEAD_LEN - 2, 0); // 收取包头 if (iRet <= 0) { return -1; } iTotal = iTotal + iRet; USHORT nDataLen = *(USHORT*)(buff+PACKHEAD_LEN-2); // 数据长度 if (nDataLen > MAX_LEN) { return -3; } startTime = time(NULL); iRet = 0; int nCheck = 0; while (1) { iRet = recv(sock, buff+iTotal, 2+nDataLen-nCheck, 0); // 收取数据和校验码 if (iRet <= 0) { return -1; } iTotal = iTotal + iRet; nCheck += iRet; if (nCheck == nDataLen + 2) break; if (time(NULL) - startTime > MAXDELAYTIME) { return -4; } } return iTotal; } /* ============== 获取SOCKET列表信息 参数: mapSevSocket:SOCKET信息结构 返回值: 无 *///============= void CServerSocket::GetSvrSockMap(MapSvrSocket & mapSevSocket) { EnterCriticalSection(&m_CriticalSection); mapSevSocket = m_mapSvrSocket; LeaveCriticalSection(&m_CriticalSection); } /* ============== 关闭Socket连接 返回值: sock SOCKET套接字 参数: 无 *///============= void CServerSocket::CloseClientSocket(SOCKET sock) { EnterCriticalSection(&m_CriticalSection); itSvrSocket itSocket = m_mapSvrSocket.find(sock); if (itSocket != m_mapSvrSocket.end()) { delete (LPSvrSocket)itSocket->second; m_mapSvrSocket.erase(itSocket); } closesocket(sock); LeaveCriticalSection(&m_CriticalSection); } /* ============== 服务器接收消息函数。 参数: buff: 接收到的数据,即填满实参内存,实参需要是一个已经分配内存的缓冲区. whichSocket: 表示哪一个套接字开始接收,对应于m_SvrSocketBody的下标。 返回值: 0 成功. 1 失败,在返回1以前,显示错误原因。 *///============= void CServerSocket::GetError(DWORD error) { char strError[256] = {‘\0‘}; switch(error) { case WSANOTINITIALISED: strcpy(strError,"初始化错误"); break; case WSAENOTCONN: strcpy(strError,"对方没有启动"); break; case WSAEWOULDBLOCK : strcpy(strError,"对方已经关闭"); break; case WSAECONNREFUSED: strcpy(strError,"连接的尝试被拒绝"); break; case WSAENOTSOCK: strcpy(strError,"在一个非套接字上尝试了一个操作"); break; case WSAEADDRINUSE: strcpy(strError,"特定的地址已在使用中"); break; case WSAECONNRESET: strcpy(strError,"与主机的连接被关闭"); break; case 2: strcpy(strError,"对方已经有一个套接字在连接状态,对于同一个用户不能进行多个套接字连接。"); break; case 3: strcpy(strError,"套接字非空,检查是否已经使用该socket进行了侦听?"); break; case 100: strcpy(strError,"连接队列已满,请稍候!"); break; case 101: strcpy(strError,"队列空,操作非法"); break; default: strcpy(strError,"低级错误"); break; } TRACE("SOCKET 错误:%s\r\n", strError); }
标签:校验码 tags private 列表 == nts 检测 server ldb
原文地址:https://www.cnblogs.com/osbreak/p/9533369.html