ZSChatServer线程设计模型

ZSChatServer 线程设计模型
Lanno Ckeeke
LC2006061401
Server 与Client 交互方式
Server启动后进入监听状态,等待Client的连接。所有Client的请求都必经过Server,再由Server发送给指定的Server。
 
完成功能
       建立服务器的线程模型,并能够接收来自客户端的请求(包含端口5005和5006的数据)。
 
ZSChat 消息定义
版本号
Version
消息名称
MsgName
消息ID
MsgID
消息时间
MsgTime
消息源地址
MsgSrc
消息目的地址
MsgDst
消息目的地址个数
MsgDstCnt
消息长度
MsgLen
消息内容
MsgCont
 
 
 
消息控制包待定。
 
Server 消息处理线程
主程序负责对对Winsock的加载,并创建消息监听线程和消息控制监听线程。
1.        启动Winsock
2.        创建用于监听消息的线程
3.        创建用于监听消息控制的线程
4.        卸载Winsocket
 
Server启动两个子线程,一个用于监听Client的请求,名称为SZListenMsgThread;另一个为处理ZSMsg的线程,名称为SZMsgThread。其监听端口号为5005。
 
SZListenMsgThread功能:
1.        消息控制监听 Socket
2.        设置消息监听地址
3.        监听Socket
4.        准备接受来自客户端的请求
5.        创建处理消息的线程
 
SZMsgThread功能
1.        取得与客户端建立连接的SOCKET
2.        从SOCK接收数据,并将之保存到szBuf中
3.        从SOCK接收数据,并将之保存到szBuf中
 
Server 消息控制线程
一个用于监听Client的消息控制请求,名称为SZListenMsgCtrlThreads;与之对应的处理线程为SZMsgCtrlThread。其监听号为5006。
这两个线程与消息处理线程格式设计一样,只是针对不同的消息包。
 
程序代码
  1. // ZSChatServer.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include <WinSock2.h>
  5. #include <Windows.h>
  6. #include <iostream>
  7. using namespace std;
  8.  
  9. #define DEFAULT_BUFFER 4096
  10.  
  11. typedef struct ZSMSG {
  12.      int Version;
  13.      int MsgID;
  14.      int MsgTime;
  15.      sockaddr_in MsgSrc;
  16.      sockaddr_in MsgDst;
  17.      int MsgDstCnt;
  18.      int MsgLen;
  19. }ZSMSG;
  20.  
  21. typedef struct ZSThreadData {
  22.      int nPort;
  23.      SOCKET scSocket;
  24.      SOCKET scAccept;
  25.      sockaddr_in siSockAddr;
  26. }ZSThreadData;
  27.  
  28. DWORD WINAPI SZMsgThread(LPVOID lpParam){
  29.      ZSThreadData *pThreadData = (ZSThreadData*)lpParam;
  30.  
  31.      //取得与客户端建立连接的SOCKET
  32.      SOCKET sock = (SOCKET)(pThreadData->scAccept);
  33.      char szBuf[DEFAULT_BUFFER]; //接收数据的BUFFER
  34.      int nRet =0,                //每次调用SEND实际发送了多少数据
  35.          nLeft = 0,                  //还剩余多少数据未发送
  36.          idx =0;                     //一共发送多少数据
  37.  
  38.      while (1) {
  39.          //从SOCK接收数据,并将之保存到szBuf中
  40.          nRet = recv(sock,szBuf,DEFAULT_BUFFER,0);
  41.          ZSMSG* pZSMsg = reinterpret_cast<ZSMSG*>(szBuf);
  42.          if (nRet == 0) {
  43.               //正常关闭
  44.               break;
  45.          }else if (nRet == SOCKET_ERROR) {
  46.               //SOCKET错误
  47.               cout <<hex << "recv Error = " << WSAGetLastError() <<endl;
  48.               break;
  49.          }
  50.          szBuf[nRet] = '/0';
  51.          cout <<"Recv = " << szBuf <<endl;
  52.  
  53.          if (1) {
  54.               nLeft = nRet;
  55.               idx = 0;
  56.               while (nLeft > 0) {
  57.                    //向客户端发送回应数据
  58.                    nRet = send(sock,&szBuf[idx],nLeft,0);
  59.                    if (nRet == 0) {
  60.                        break;
  61.                    }else if (nRet == SOCKET_ERROR) {
  62.                        //发送数据出错
  63.                        cout << hex << "recv error = " << WSAGetLastError() << endl;
  64.                        break;
  65.                    }
  66.                    nLeft -= nRet;     //还剩余多少字节
  67.                    idx += nRet; //已发送多少字节  
  68.  
  69.               }
  70.          }
  71.      }
  72.  
  73.      return 0;
  74. }
  75.  
  76. DWORD WINAPI SZMsgCtrlThread(LPVOID lpParam){
  77.      ZSThreadData *pThreadData = (ZSThreadData*)lpParam;
  78.  
  79.      //接受连接的SOCKET
  80.      SOCKET sock = (SOCKET)(pThreadData->scAccept);
  81.      char szBuf[DEFAULT_BUFFER]; //接收数据的BUFFER
  82.      int nRet =0,                //每次调用SEND实际发送了多少数据
  83.          nLeft = 0,                  //还剩余多少数据未发送
  84.          idx =0;                     //一共发送多少数据
  85.  
  86.      while (1) {
  87.          //从SOCK接收数据,并将之保存到szBuf中
  88.          nRet = recv(sock,szBuf,DEFAULT_BUFFER,0);
  89.          ZSMSG* pZSMsg = reinterpret_cast<ZSMSG*>(szBuf);
  90.          if (nRet == 0) {
  91.               //正常关闭
  92.               break;
  93.          }else if (nRet == SOCKET_ERROR) {
  94.               //SOCKET错误
  95.               cout <<hex << "recv Error = " << WSAGetLastError() <<endl;
  96.               break;
  97.          }
  98.           szBuf[nRet] = '/0';
  99.          cout <<"Recv = " << szBuf <<endl;
  100.  
  101.          if (1) {
  102.               nLeft = nRet;
  103.               idx = 0;
  104.               while (nLeft > 0) {
  105.                    //发送数据
  106.                    nRet = send(sock,&szBuf[idx],nLeft,0);
  107.                    if (nRet == 0) {
  108.                        break;
  109.                    }else if (nRet == SOCKET_ERROR) {
  110.                        //发送数据出错
  111.                        cout << hex << "recv error = " << WSAGetLastError() << endl;
  112.                        break;
  113.                    }
  114.                    nLeft -= nRet;     //还剩余多少字节
  115.                    idx += nRet; //已发送多少字节  
  116.  
  117.               }
  118.          }
  119.      }
  120.  
  121.      return 0;
  122. }
  123. DWORD WINAPI SZListenMsgThread(LPVOID lpParam){
  124.  
  125.      ZSThreadData* pThreadData = (ZSThreadData*)lpParam;
  126.      SOCKET scClientSocket;
  127.  
  128.      HANDLE hThread = NULL;
  129.      DWORD dwThreadID = 0;
  130.     
  131.      //(1)消息控制监听 Socket
  132.      pThreadData->scSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
  133.      if (pThreadData->scSocket == SOCKET_ERROR) {
  134.          cout << "scMSgCtrlListen socket Error = " << hex << WSAGetLastError() << endl;
  135.          return 1;
  136.      }
  137.  
  138.      //(2)设置消息监听地址
  139.      pThreadData->siSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  140.      pThreadData->siSockAddr.sin_family = AF_INET;
  141.      pThreadData->siSockAddr.sin_port = htons(pThreadData->nPort);
  142.  
  143.     if (bind(pThreadData->scSocket,
  144.          (struct sockaddr*)&(pThreadData->siSockAddr),
  145.          sizeof(pThreadData->siSockAddr)) == SOCKET_ERROR) {
  146.               cout << "bind Error = " << hex << WSAGetLastError() << endl;
  147.               return 1;
  148.     }
  149.          //(3)监听Socket
  150.          listen(pThreadData->scSocket,0);
  151.          while (1) {
  152.               sockaddr_in siClient;
  153.               int nClinetAddr = sizeof(siClient);
  154.               //(4)准备接受来自客户端的请求。
  155.               pThreadData->scAccept = accept(pThreadData->scSocket,(struct sockaddr*)&siClient,&nClinetAddr);
  156.              
  157.               /*
  158.                *
  159.                现象:返回2726
  160.                原因:将pThreadData->scAccept = pThreadData->scSocket
  161.                */
  162.  
  163.               if (pThreadData->scAccept == SOCKET_ERROR) {
  164.                    cout<< hex << "socket Error = " << WSAGetLastError() << endl;
  165.                    return 1;
  166.               }
  167.               //(5)创建处理消息的线程
  168.               hThread = CreateThread(NULL,0,SZMsgThread,(LPVOID)pThreadData,0,&dwThreadID);
  169.               if (hThread == NULL) {
  170.                    cout << hex << "CreateThread Error = " << GetLastError() << endl;
  171.               }
  172.  
  173.          }
  174. }
  175. DWORD WINAPI SZListenMsgCtrlThread(LPVOID lpParam){
  176.  
  177.      ZSThreadData* pThreadData = (ZSThreadData*)lpParam;
  178.      SOCKET scClientSocket;
  179.  
  180.      HANDLE hThread = NULL;
  181.      DWORD dwThreadID = 0;
  182.  
  183.      //消息控制监听 Socket
  184.      pThreadData->scSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
  185.      if (pThreadData->scSocket == SOCKET_ERROR) {
  186.          cout << "scMSgCtrlListen socket Error = " << hex << WSAGetLastError() << endl;
  187.          return 1;
  188.      }
  189.  
  190.      //设置消息监听地址
  191.      pThreadData->siSockAddr.sin_addr.s_addr =inet_addr("127.0.0.1");// htonl(INADDR_ANY);
  192.      pThreadData->siSockAddr.sin_family = AF_INET;
  193.      pThreadData->siSockAddr.sin_port = htons(pThreadData->nPort);
  194.  
  195.      if (bind(pThreadData->scSocket,
  196.          (struct sockaddr*)&(pThreadData->siSockAddr),
  197.          sizeof(pThreadData->siSockAddr)) == SOCKET_ERROR) {
  198.          }
  199.          listen(pThreadData->scSocket,0);
  200.          while (1) {
  201.               sockaddr_in siClient;
  202.               int nClinetAddr = sizeof(siClient);
  203.               pThreadData->scAccept = accept(pThreadData->scSocket,(struct sockaddr*)&siClient,&nClinetAddr);
  204.  
  205.               if (pThreadData->scAccept == SOCKET_ERROR) {
  206.                    cout << hex << "accept Error = " << WSAGetLastError() << endl;
  207.                    return 1;
  208.               }
  209.  
  210.               hThread = CreateThread(NULL,0,SZMsgCtrlThread,(LPVOID)pThreadData,0,&dwThreadID);
  211.               if (hThread == NULL) {
  212.                    cout << hex << "CreateThread Error = " << GetLastError() << endl;
  213.               }
  214.          }
  215. }
  216. int _tmain(int argc, _TCHAR* argv[])
  217. {
  218.      //定义变量
  219.      int nMsgPort = 5005; //消息监听端口
  220.      int nMsgCtrlPort = 5006;//消息控制监听端口
  221.  
  222.       SOCKET scMsgListen,scMsgProcess;              //消息监听Socket和消息处理Socket
  223.       SOCKET scMsgCtrlListen,scMsgCtrlProcess; //消息控制Socket和消息控制处理Socket
  224.  
  225.       sockaddr_in siMsgListen,siMsgProcess;         //消息监听和消息处理地址
  226.       sockaddr_in siMsgCtrlListen,siMsgCtrlProcess;//消息控制监听和消息控制处理地址
  227.  
  228.       HANDLE hMsgThread[2], //消息句柄
  229.           hMsgCtrlThread = NULL; //消息处理句柄
  230.  
  231.       DWORD dwMsgThread = 0,     //消息线程ID
  232.           dwMsgCtrlThread = 0; //消息控制线程ID
  233.  
  234.       //(1)启动Winsock
  235.       WSADATA wsd;
  236.       if(WSAStartup(MAKEWORD(2,2),&wsd) != 0){
  237.           cout <<"WSAStartup Error = " << WSAGetLastError() << endl;
  238.           return 1;
  239.       }
  240.  
  241.       ZSThreadData zstd;
  242.       zstd.nPort = nMsgPort;
  243.  
  244.       //(2)创建用于监听消息的线程
  245.       hMsgThread[0] = CreateThread(NULL,0,SZListenMsgThread,(LPVOID)&zstd,0,&dwMsgThread);
  246.       if (hMsgThread[0] == NULL) {
  247.           cout << hex << "CreateThread Error = " << GetLastError() << endl;
  248.           return 1;
  249.       }
  250.  
  251.       //(3)创建用于监听消息控制的线程
  252.       ZSThreadData zsListenMsgCtrl;
  253.       zsListenMsgCtrl.nPort = nMsgCtrlPort;
  254.       hMsgThread[1] = CreateThread(NULL,0,SZListenMsgCtrlThread,(LPVOID)&zsListenMsgCtrl,0,&dwMsgCtrlThread);
  255.       if (hMsgThread[1] == NULL) {
  256.           cout << hex << "CreateThread Error = " << GetLastError() << endl;
  257.           return 1;
  258.       }  
  259.       WaitForMultipleObjects(2,hMsgThread,TRUE,INFINITE);
  260.  
  261.       CloseHandle(hMsgThread[0]);
  262.       CloseHandle(hMsgThread[1]);
  263.  
  264.       //(4)卸载Winsocket
  265.       WSACleanup();
  266.       system("pause");
  267.      return 0;
  268. }
  269.  

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值