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。
这两个线程与消息处理线程格式设计一样,只是针对不同的消息包。
程序代码
- // ZSChatServer.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <WinSock2.h>
- #include <Windows.h>
- #include <iostream>
- using namespace std;
- #define DEFAULT_BUFFER 4096
- typedef struct ZSMSG {
- int Version;
- int MsgID;
- int MsgTime;
- sockaddr_in MsgSrc;
- sockaddr_in MsgDst;
- int MsgDstCnt;
- int MsgLen;
- }ZSMSG;
- typedef struct ZSThreadData {
- int nPort;
- SOCKET scSocket;
- SOCKET scAccept;
- sockaddr_in siSockAddr;
- }ZSThreadData;
- DWORD WINAPI SZMsgThread(LPVOID lpParam){
- ZSThreadData *pThreadData = (ZSThreadData*)lpParam;
- //取得与客户端建立连接的SOCKET
- SOCKET sock = (SOCKET)(pThreadData->scAccept);
- char szBuf[DEFAULT_BUFFER]; //接收数据的BUFFER
- int nRet =0, //每次调用SEND实际发送了多少数据
- nLeft = 0, //还剩余多少数据未发送
- idx =0; //一共发送多少数据
- while (1) {
- //从SOCK接收数据,并将之保存到szBuf中
- nRet = recv(sock,szBuf,DEFAULT_BUFFER,0);
- ZSMSG* pZSMsg = reinterpret_cast<ZSMSG*>(szBuf);
- if (nRet == 0) {
- //正常关闭
- break;
- }else if (nRet == SOCKET_ERROR) {
- //SOCKET错误
- cout <<hex << "recv Error = " << WSAGetLastError() <<endl;
- break;
- }
- szBuf[nRet] = '/0';
- cout <<"Recv = " << szBuf <<endl;
- if (1) {
- nLeft = nRet;
- idx = 0;
- while (nLeft > 0) {
- //向客户端发送回应数据
- nRet = send(sock,&szBuf[idx],nLeft,0);
- if (nRet == 0) {
- break;
- }else if (nRet == SOCKET_ERROR) {
- //发送数据出错
- cout << hex << "recv error = " << WSAGetLastError() << endl;
- break;
- }
- nLeft -= nRet; //还剩余多少字节
- idx += nRet; //已发送多少字节
- }
- }
- }
- return 0;
- }
- DWORD WINAPI SZMsgCtrlThread(LPVOID lpParam){
- ZSThreadData *pThreadData = (ZSThreadData*)lpParam;
- //接受连接的SOCKET
- SOCKET sock = (SOCKET)(pThreadData->scAccept);
- char szBuf[DEFAULT_BUFFER]; //接收数据的BUFFER
- int nRet =0, //每次调用SEND实际发送了多少数据
- nLeft = 0, //还剩余多少数据未发送
- idx =0; //一共发送多少数据
- while (1) {
- //从SOCK接收数据,并将之保存到szBuf中
- nRet = recv(sock,szBuf,DEFAULT_BUFFER,0);
- ZSMSG* pZSMsg = reinterpret_cast<ZSMSG*>(szBuf);
- if (nRet == 0) {
- //正常关闭
- break;
- }else if (nRet == SOCKET_ERROR) {
- //SOCKET错误
- cout <<hex << "recv Error = " << WSAGetLastError() <<endl;
- break;
- }
- szBuf[nRet] = '/0';
- cout <<"Recv = " << szBuf <<endl;
- if (1) {
- nLeft = nRet;
- idx = 0;
- while (nLeft > 0) {
- //发送数据
- nRet = send(sock,&szBuf[idx],nLeft,0);
- if (nRet == 0) {
- break;
- }else if (nRet == SOCKET_ERROR) {
- //发送数据出错
- cout << hex << "recv error = " << WSAGetLastError() << endl;
- break;
- }
- nLeft -= nRet; //还剩余多少字节
- idx += nRet; //已发送多少字节
- }
- }
- }
- return 0;
- }
- DWORD WINAPI SZListenMsgThread(LPVOID lpParam){
- ZSThreadData* pThreadData = (ZSThreadData*)lpParam;
- SOCKET scClientSocket;
- HANDLE hThread = NULL;
- DWORD dwThreadID = 0;
- //(1)消息控制监听 Socket
- pThreadData->scSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
- if (pThreadData->scSocket == SOCKET_ERROR) {
- cout << "scMSgCtrlListen socket Error = " << hex << WSAGetLastError() << endl;
- return 1;
- }
- //(2)设置消息监听地址
- pThreadData->siSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
- pThreadData->siSockAddr.sin_family = AF_INET;
- pThreadData->siSockAddr.sin_port = htons(pThreadData->nPort);
- if (bind(pThreadData->scSocket,
- (struct sockaddr*)&(pThreadData->siSockAddr),
- sizeof(pThreadData->siSockAddr)) == SOCKET_ERROR) {
- cout << "bind Error = " << hex << WSAGetLastError() << endl;
- return 1;
- }
- //(3)监听Socket
- listen(pThreadData->scSocket,0);
- while (1) {
- sockaddr_in siClient;
- int nClinetAddr = sizeof(siClient);
- //(4)准备接受来自客户端的请求。
- pThreadData->scAccept = accept(pThreadData->scSocket,(struct sockaddr*)&siClient,&nClinetAddr);
- /*
- *
- 现象:返回2726
- 原因:将pThreadData->scAccept = pThreadData->scSocket
- */
- if (pThreadData->scAccept == SOCKET_ERROR) {
- cout<< hex << "socket Error = " << WSAGetLastError() << endl;
- return 1;
- }
- //(5)创建处理消息的线程
- hThread = CreateThread(NULL,0,SZMsgThread,(LPVOID)pThreadData,0,&dwThreadID);
- if (hThread == NULL) {
- cout << hex << "CreateThread Error = " << GetLastError() << endl;
- }
- }
- }
- DWORD WINAPI SZListenMsgCtrlThread(LPVOID lpParam){
- ZSThreadData* pThreadData = (ZSThreadData*)lpParam;
- SOCKET scClientSocket;
- HANDLE hThread = NULL;
- DWORD dwThreadID = 0;
- //消息控制监听 Socket
- pThreadData->scSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
- if (pThreadData->scSocket == SOCKET_ERROR) {
- cout << "scMSgCtrlListen socket Error = " << hex << WSAGetLastError() << endl;
- return 1;
- }
- //设置消息监听地址
- pThreadData->siSockAddr.sin_addr.s_addr =inet_addr("127.0.0.1");// htonl(INADDR_ANY);
- pThreadData->siSockAddr.sin_family = AF_INET;
- pThreadData->siSockAddr.sin_port = htons(pThreadData->nPort);
- if (bind(pThreadData->scSocket,
- (struct sockaddr*)&(pThreadData->siSockAddr),
- sizeof(pThreadData->siSockAddr)) == SOCKET_ERROR) {
- }
- listen(pThreadData->scSocket,0);
- while (1) {
- sockaddr_in siClient;
- int nClinetAddr = sizeof(siClient);
- pThreadData->scAccept = accept(pThreadData->scSocket,(struct sockaddr*)&siClient,&nClinetAddr);
- if (pThreadData->scAccept == SOCKET_ERROR) {
- cout << hex << "accept Error = " << WSAGetLastError() << endl;
- return 1;
- }
- hThread = CreateThread(NULL,0,SZMsgCtrlThread,(LPVOID)pThreadData,0,&dwThreadID);
- if (hThread == NULL) {
- cout << hex << "CreateThread Error = " << GetLastError() << endl;
- }
- }
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- //定义变量
- int nMsgPort = 5005; //消息监听端口
- int nMsgCtrlPort = 5006;//消息控制监听端口
- SOCKET scMsgListen,scMsgProcess; //消息监听Socket和消息处理Socket
- SOCKET scMsgCtrlListen,scMsgCtrlProcess; //消息控制Socket和消息控制处理Socket
- sockaddr_in siMsgListen,siMsgProcess; //消息监听和消息处理地址
- sockaddr_in siMsgCtrlListen,siMsgCtrlProcess;//消息控制监听和消息控制处理地址
- HANDLE hMsgThread[2], //消息句柄
- hMsgCtrlThread = NULL; //消息处理句柄
- DWORD dwMsgThread = 0, //消息线程ID
- dwMsgCtrlThread = 0; //消息控制线程ID
- //(1)启动Winsock
- WSADATA wsd;
- if(WSAStartup(MAKEWORD(2,2),&wsd) != 0){
- cout <<"WSAStartup Error = " << WSAGetLastError() << endl;
- return 1;
- }
- ZSThreadData zstd;
- zstd.nPort = nMsgPort;
- //(2)创建用于监听消息的线程
- hMsgThread[0] = CreateThread(NULL,0,SZListenMsgThread,(LPVOID)&zstd,0,&dwMsgThread);
- if (hMsgThread[0] == NULL) {
- cout << hex << "CreateThread Error = " << GetLastError() << endl;
- return 1;
- }
- //(3)创建用于监听消息控制的线程
- ZSThreadData zsListenMsgCtrl;
- zsListenMsgCtrl.nPort = nMsgCtrlPort;
- hMsgThread[1] = CreateThread(NULL,0,SZListenMsgCtrlThread,(LPVOID)&zsListenMsgCtrl,0,&dwMsgCtrlThread);
- if (hMsgThread[1] == NULL) {
- cout << hex << "CreateThread Error = " << GetLastError() << endl;
- return 1;
- }
- WaitForMultipleObjects(2,hMsgThread,TRUE,INFINITE);
- CloseHandle(hMsgThread[0]);
- CloseHandle(hMsgThread[1]);
- //(4)卸载Winsocket
- WSACleanup();
- system("pause");
- return 0;
- }