当前位置: 首页 > news >正文

C++多线程服务器

C++多线程服务器

因为自己同时在看多本书,之前看过《TCP/IP 网络编程》一书,其中有一个自己编写一个多线程服务器的例子,于是就把代码直接抄了一变。

在学习网络编程前需要先了解网络的7层模型。

具体代码如下:

服务器端:

include <iostream>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;#define BUF_SIZE 100
#define MAX_CLNT 256unsigned WINAPI HandleClient(void* pvoid);
void SendMeg(const char* pMsg,int nLen);
void ErrorHandle(const char* pMsg);int nCountClient = 0;
SOCKET clntSocket[MAX_CLNT];
HANDLE hMutex;int main(int argc,char* argv[])
{WSADATA wsaData;SOCKET hServSock, hClntSock;SOCKADDR_IN servAdr, clntAdr;int clntAdrSz;HANDLE hTread;if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){ErrorHandle("WSAStartup Error");}hMutex = CreateMutex(NULL,FALSE,NULL);hServSock = socket(PF_INET,SOCK_STREAM,0);memset(&servAdr,0,sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);servAdr.sin_port = htons(9000);if (bind(hServSock, (SOCKADDR*)&servAdr,sizeof(servAdr)) == SOCKET_ERROR){ErrorHandle("bind Error");}if (listen(hServSock,5) == SOCKET_ERROR){ErrorHandle("listen Error");}while (1){clntAdrSz = sizeof(clntAdr);cout << "[Server]:Wait for client to Connect..." << endl;hClntSock = accept(hServSock,(sockaddr*)&clntAdr,&clntAdrSz);::WaitForSingleObject(hMutex,INFINITE);clntSocket[nCountClient++] = hClntSock;ReleaseMutex(hMutex);hTread = (HANDLE)_beginthreadex(NULL,0, HandleClient,(void*)&hClntSock,0,NULL);printf("[Server]:Connenct Client IP:%s\n",inet_ntoa(clntAdr.sin_addr));}closesocket(hServSock);WSACleanup();return 0;
}unsigned WINAPI HandleClient(void* pvoid)
{SOCKET hClntSock = *((SOCKET*)(pvoid));int strLen = 0;int i;char szBuff[BUF_SIZE];memset(szBuff,0, sizeof(char)*BUF_SIZE);while ((strLen = recv(hClntSock, szBuff, sizeof(szBuff), 0)) != 0){printf("[Server]:recv %s from Client.\n",szBuff);SendMeg(szBuff, strLen);}::WaitForSingleObject(hMutex, INFINITE);for (i = 0;i< nCountClient;i++){// 移除断开连接的套接字if (hClntSock == clntSocket[i]){while (i++ < nCountClient - 1){clntSocket[i] = clntSocket[i + 1];}break;  }}nCountClient--;ReleaseMutex(hMutex);closesocket(hClntSock);return 0;
}void SendMeg(const char* pMsg, int nLen)
{int i;::WaitForSingleObject(hMutex, INFINITE);for (int i=0;i< nCountClient;i++){send(clntSocket[i], pMsg, nLen,0);printf("[Server]:send %s to Client.\n",pMsg);}ReleaseMutex(hMutex);
}void ErrorHandle(const char* pMsg)
{fputs(pMsg,stderr);fputc('\n',stderr);exit(1);
}

代码说明:其中修改了一下在控制台中输出的信息。

客户端代码:

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;#define BUF_SIZE 100
#define NAME_SIZE 20unsigned WINAPI SendMsg(void* arg);
unsigned WINAPI RecvMsg(void* arg);
void ErrorHandle(const char* msg);char name[NAME_SIZE] = "[DEFAULT]";
char msg[BUF_SIZE];int main(int argc,char* argv[])
{WSADATA wsaData;SOCKET hSock;SOCKADDR_IN servAdr;HANDLE hSndThread, hRcvThread;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ErrorHandle("WSAStartup Error()");}hSock = socket(PF_INET,SOCK_STREAM,0);memset(&servAdr,0,sizeof(servAdr));servAdr.sin_family = AF_INET;servAdr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");servAdr.sin_port = htons(9000);if (connect(hSock,(sockaddr*)&servAdr,sizeof(servAdr)) == SOCKET_ERROR){ErrorHandle("Connect Error");}cout << "Connect To Server success" << endl;hSndThread = (HANDLE)_beginthreadex(NULL,0,SendMsg,(void*)(&hSock),0,NULL);hRcvThread = (HANDLE)_beginthreadex(NULL,0,RecvMsg, (void*)(&hSock), 0, NULL);WaitForSingleObject(hSndThread,INFINITE);WaitForSingleObject(hRcvThread,INFINITE);closesocket(hSock);WSACleanup();return 0;
}unsigned WINAPI SendMsg(void* arg)
{SOCKET hSock = *((SOCKET*)arg);char nameMsg[BUF_SIZE + NAME_SIZE];while (1){cout << "[Client]:Please enter your msg to send to Server..." << endl;fgets(msg, BUF_SIZE,stdin);if (strcmp(msg,"q\n") == 0||strcmp(msg,"Q\n") == 0){closesocket(hSock);exit(0);}send(hSock,msg,strlen(msg),0);printf("[Client]:send %s to Server\n", msg);}return 0;
}unsigned WINAPI RecvMsg(void* arg)
{SOCKET hSock = *((SOCKET*)arg);char nameMsg[BUF_SIZE + NAME_SIZE];int strLen;while (1){strLen = recv(hSock, nameMsg, BUF_SIZE + NAME_SIZE-1,0);if (strLen == -1)return-1;nameMsg[strLen] = 0;printf("[Client]:recv %s From Server\n", nameMsg);}return 0;
}void ErrorHandle(const char* msg)
{fputs(msg, stderr);fputc('\n', stderr);exit(1);
}

流程说明:先运行服务器,等待客户端的连接,客户端连接后由客户端输入字符串,然后发送给服务器,服务器再把接受到的字符串发回给客户端,这样就是一个回声服务器了。

代码运行效果:

wechat_2025-08-10_160759_866
有关多线程网络编程的更多内容,大家可以参考《TCP/IP 网络编程》一书。

http://www.dtcms.com/a/325061.html

相关文章:

  • MySQL基础知识总结
  • MySQL 序列使用详细说明
  • RAG (Retrieval-Augmented Generation) 原理详解与实例
  • 专题二_滑动窗口_最小覆盖子串
  • 【lucene】BlockDocsEnum 跟BlockImpactsDocsEnum 的区别
  • C++入门学习5
  • Boost.Asio io_service 与 线程 的分析
  • playwright-mcp 项目全解析:从理论到实践
  • 消息队列系统测试报告
  • Effective C++ 条款33:避免遮掩继承而来的名称
  • 企业临时文件分享方案:基于本地加密的轻量级实现
  • Unity3D游戏中如何制作空气墙
  • 动态群签名-DGS:实现抗女巫攻击
  • eBay功能升级:卖家提升流量与转化的新契机
  • 深入解析NumPy广播机制:让不同形状的数组无缝运算
  • 【MySQL——第三章 :MySQL库表操作】
  • Redis 数据类型和单线程模型补充
  • HyDE 在 RAG 知识问答助手中的应用解析
  • CentOS7安装和使用Workbench
  • AtomicStampedReference解决方案
  • 基于python/django框架的车型识别系统
  • 复现论文《基于Retinex理论和深度学习的低照度图像增强算法研究》
  • 问津集 #4:The Five-Minute Rule for the Cloud: Caching in Analytics Systems
  • windows运维
  • SF-CPI-SAP问题收集24:集成地址信息的村里字段无法页面显示问题
  • ECharts 的理解和简单应用笔记
  • 【无标题】消息队列(Message Queue)是一种**进程间通信(IPC)机制
  • 深度学习-卷积神经网络-AlexNet
  • index.d.ts 是什么?作用 + 怎么生成?
  • 糖果大冒险:公平分发的智慧挑战