123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #include "stdafx.h"
- #include <afxtempl.h>
- #include <winsock2.h>
- #include <Mswsock.h>
- #include <list>
- #include <vector>
- #include <string>
- #include <process.h>
- #include <time.h>
- #include <map>
- #include "iostream"
- using namespace std;
- #define SOCKET_BUF_SIZE 10240 // 发送、接收缓冲区最大长度,10K
- #define OVERLAPPED_DELIVER_SEND 0 // 发送数据
- #define OVERLAPPED_DELIVER_RECV 2 // 接收数据
- class MyTcpSrv;
- // 客户端套接字元
- typedef struct _CLIENT_ELEMENT
- {
- SOCKET s_socket; // 客户端SOCKET套接字
- SOCKADDR_IN s_clientInfo; // 客户端终端信息
- time_t s_tVisitTM; // 访问时间
- bool s_bFirstFrame; // 第一帧标志位
- _CLIENT_ELEMENT()
- {
- s_socket = INVALID_SOCKET;
- }
- } TS_CLIENT_ELEMENT, * LPTS_CLIENT_ELEMENT;
- // 通信载体,此处使用尾随参数的解决思路,故而OVERLAPPED必须为第一个参数
- typedef struct _SOCKET_INFORMATION
- {
- OVERLAPPED s_overlapped;
- CHAR s_buffer[SOCKET_BUF_SIZE]; // 存储接收的字符
- int s_nBufLen; // 接收的长度
- WSABUF s_dataBuf; // 接收缓冲区,为OS自动填充区
- LPTS_CLIENT_ELEMENT s_lpClientElement; // 客户端套接字元
- UINT s_uDeliverType; // 异步请求类型
- int s_uAntiSendSize; // 预期发送字节数
- bool s_bIsDiscard; // 作废标志位
- MyTcpSrv* s_pThis; // 所有者
- _SOCKET_INFORMATION()
- {
- s_lpClientElement = NULL;
- s_pThis = NULL;
- }
- } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
- // TCPSrv、UDP网络报文数据结构
- typedef struct _netPara
- {
- UCHAR s_szBuf[SOCKET_BUF_SIZE]; // 数据缓存
- WORD s_wBufLen; // 数据长度
- // 追加字符
- void Append(_netPara* pNet)
- {
- memcpy(s_szBuf + s_wBufLen,pNet->s_szBuf,min(SOCKET_BUF_SIZE - s_wBufLen, pNet->s_wBufLen));
- s_wBufLen += pNet->s_wBufLen;
- }
- // 释放
- void Release(UINT uSize)
- {
- UCHAR szBuf[SOCKET_BUF_SIZE];
- memcpy(szBuf, s_szBuf + uSize, s_wBufLen - uSize);
- memset(s_szBuf, 0, SOCKET_BUF_SIZE);
- memcpy(s_szBuf, szBuf, s_wBufLen - uSize);
- s_wBufLen = s_wBufLen - uSize;
- }
- }SNetPara, * LPNetPara;
- // 终端信息结构
- typedef struct _terminal_info
- {
- string s_ip; // IP地址
- USHORT s_uPort; // 端口号
- // 重载<运算符,以支持作为map的key
- friend inline bool operator < (const _terminal_info &ls, const _terminal_info &rs);
- friend inline bool operator == (const _terminal_info &ls, const _terminal_info &rs);
- }TERMINAL_INFO, * LPTERMINAL_INFO;
- // LESS
- bool operator < (const _terminal_info& ls, const _terminal_info& rs)
- {
- return (ls.s_ip < rs.s_ip || (ls.s_ip == rs.s_ip && ls.s_uPort < rs.s_uPort));
- }
- // EQUAL
- bool operator == (const _terminal_info& ls, const _terminal_info& rs)
- {
- return (ls.s_ip == rs.s_ip && ls.s_uPort == rs.s_uPort);
- }
- typedef vector<TS_CLIENT_ELEMENT> VClnt; // 客户端信息列表
- typedef list<SNetPara> LNetPara; // 接收信息列表
- typedef map<TERMINAL_INFO, SNetPara> MNetDatagram; // 网络数据包
- // TCP服务器端
- class MyTcpSrv
- {
- private:
- CRITICAL_SECTION m_csLock; // 临界对象,冲突锁
- HANDLE m_hIOCP; // 完成端口句柄
- SOCKADDR_IN m_LocalAddr; // 本地终端地址
- SOCKET m_sLinstenSocket; // 侦听套接字
- HANDLE m_hListenThread; // 侦听线程
- UINT m_nListenThreadId; // 侦听线程ID
- HANDLE m_hListenEventExit; // 侦听线程退出事件对象,用于退出侦听线程时通知子线程关闭
- SYSTEM_INFO m_sysInfo; // 系统信息,其中包含处理器等信息
- VClnt m_clntList; // 客户端清单
- MNetDatagram m_netParaMap; // 接收信息列表
- public:
- MyTcpSrv()
- {
- InitializeCriticalSection(&m_csLock);
- m_hIOCP = INVALID_HANDLE_VALUE;
- m_sLinstenSocket = INVALID_SOCKET;
- m_hListenThread = INVALID_HANDLE_VALUE;
- m_hListenEventExit = INVALID_HANDLE_VALUE;
- }
- ~MyTcpSrv()
- {
- DeleteCriticalSection(&m_csLock);
- }
- private:
- // 加载SOCK DLL
- bool LoadSock();
- // 设置本地终端
- bool SetLocalAddr(WORD nPort, const char *szAddr);
- // 初始化完成端口
- bool InitialIOCP();
- // 设置侦听套接字
- bool SetupListenSocket();
- // 投递接收请求
- void DeliverRecv(LPSOCKET_INFORMATION lpInfo);
- // 投递发送请求
- void DeliverSend(LPSOCKET_INFORMATION lpInfo);
- // 启动侦听线程
- bool RunListenThread();
- // 侦听例程
- UINT static WINAPI TCPListenThreadProc(LPVOID pParam);
- // 工作例程
- UINT static WINAPI ServerWorkerThread(LPVOID CompletionPortID);
- // 擦除记录
- void Erase(LPSOCKET_INFORMATION lpSocketInfo);
- // 解析获取的数据
- void OnRecvData(LPSOCKET_INFORMATION lpSocketInfo);
- // 停止侦听
- void StopListening();
- // 断开与指定客户端连接
- void DisconnectUser(SOCKADDR_IN clientAddr);
- // 断开与所有用户连接
- void DisconnectAllUsers();
- // 卸载SOCKDLL
- void UnloadSock();
- public:
- // 创建通道
- bool Create(LPTERMINAL_INFO pInfo);
- // 关闭通道
- void Close();
-
- // 读取数据
- int Read(byte byRecv[], UINT uMaxSize, LPTERMINAL_INFO pInfo);
- // 发送数据
- int Write(byte bySend[], UINT uAntiSize, LPTERMINAL_INFO pInfo);
- // 重置服务器
- bool Reset();
- // 获取客户端列表信息
- VClnt GetClinetList()
- {
- return m_clntList;
- }
- };
|