C++ TCP网络编程--服务器端多线程处理会话连接

2023-05-16

客户端程序: 

#include <winsock.h> 
#include<iostream>
#pragma comment(lib,"ws2_32.lib") 

#include <Windows.h>
#include<string>

int main()
{
	//初始化Windows Socket Application
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;

	//WinSock的注册函数,初始化底层的Windows Sockets DLL
	if (WSAStartup(sockVersion, &wsaData) != 0)
		return 0;

	//创建一个socket并返回socket的标识符
	SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sclient == INVALID_SOCKET)
	{
		std::cout << "invalid socket!" << std::endl;
		return 0;
	}
	sockaddr_in serAddr;
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(8888);
	serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
	{  			//连接失败 	
		std::cout << "connect error !" << std::endl;
		closesocket(sclient);
		return 0;
	}

	std::string data="abcdef_";

	int n = 0;
	while (1)
	{
		data = "abcdef_"+std::to_string(n);
		//std::cin >> data;
		const char * sendData;
		sendData = data.c_str();
		//string转const char* 		
		/*		send()用来将数据由指定的socket传给对方主机
		int send(int s, const void * msg, int len, unsigned int flags)
		s为已建立好连接的socket,msg指向数据内容,len则为数据长度,参数flags一般设0
		成功则返回实际传送出去的字符数,失败返回-1,错误原因存于error		*/
		send(sclient, sendData, strlen(sendData), 0);

		//接收返回的数据
		char recData[255];
		int ret = recv(sclient, recData, 255, 0);//阻塞在此处等待接收
		if (ret > 0)
		{
			recData[ret] = 0x00;
			std::cout <<"第"<<n<<"回:"<< recData << std::endl;
		}

		if (n++>20)
		{
			break;
		}

		Sleep(1000);
	}

	//关闭
	closesocket(sclient);

	WSACleanup();
	system("pause");
	return 0;
}

服务器端程序: 

#include <winsock.h> 
#include<iostream>
#pragma comment(lib,"ws2_32.lib") 
#include <Windows.h>
#include <string>


DWORD WINAPI ThreadTCP(LPVOID pParam);

int main()
{
	//初始化Windows Socket Application
	WORD sockVersion = MAKEWORD(2, 2);
	WSADATA wsaData;

	//WinSock的注册函数,初始化底层的Windows Sockets DLL
	if (WSAStartup(sockVersion, &wsaData) != 0)
		return 0;

	//创建套接字 
	SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (slisten == INVALID_SOCKET)
	{
		std::cout << "create socket error!" << std::endl;
		return 0;
	}

	//绑定IP和端口  	
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	//
	sin.sin_port = htons(8888);//指定端口,将端口号转换为网络字节顺序
	sin.sin_addr.S_un.S_addr = INADDR_ANY;

	//bind()把socket绑定到特定的网络地址上
	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		std::cout << "bind error!" << std::endl;
		return 0;
	}

	//开始监听
//启动指定的socket,监听到来的连接请求  
5指定了监听socket的等待连接缓冲区队列的最大长度,一般设为5	
	if (listen(slisten, 5) == SOCKET_ERROR)
	{
		std::cout << "listen error !" << std::endl;
		return 0;
	}

	//循环接收数据 
	SOCKET sClient;
	sockaddr_in remoteAddr;
	int nAddrlen = sizeof(remoteAddr);
	

	while (true)
	{
		std::cout << "阻塞。。。。等待连接。。。" << std::endl;
		//接收一个连接请求,并新建一个socket,原来的socket返回监听状态
		sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
		if (sClient == INVALID_SOCKET)
		{
			std::cout << "accept error !" << std::endl;
			continue;
		}

		//inet_addr()把一个标准的点分十进制的IP地址转换成长整型的地址数据
		//inet_ntoa()把长整型的IP地址数据转换成点分十进制的ASCII字符串	
		std::cout << "接受一个连接:" << inet_ntoa(remoteAddr.sin_addr)<<":"<<remoteAddr.sin_port << std::endl;


		//创建一个线程与客户端进行会话
		CreateThread(NULL, 0, ThreadTCP, (LPVOID)sClient, 0, NULL);

	}

	closesocket(slisten);

	//winsock的注销函数,从底层的Windows Sockets DLL 中撤销注册
	WSACleanup();
	system("pause");
	return 0;
}

DWORD WINAPI ThreadTCP(LPVOID pParam)
{
	SOCKET sClient = (SOCKET)pParam;

	char revData[255];
	std::string data = "hello_";
	int n = 0;
	while (1)
	{
		data = "hello_"+std::to_string(n);
		//接收数据  
		//从一个已经与对方建立连接的socket接收数据	
		int ret = recv(sClient, revData, 255, 0);//阻塞于此进行接收
		if (ret > 0)
		{
			revData[ret] = 0x00;
			std::cout << "第" << n++ << "回:" << revData << std::endl;
			//printf(revData);
		}

		//发送数据  	
		const char * sendData = data.c_str();

		向一个已经与对方建立连接的socket发送数据	
		int nb=send(sClient, sendData, strlen(sendData), 0);
		if (nb != strlen(sendData))
		{
			break;
		}
		//Sleep(5000);
	}


	//断开连接
	std::cout << "断开连接" << std::endl;
	//关闭socket,释放相应的资源
	closesocket(sClient);
	return 0;
}

 服务器端每接收一个连接,则添加一个线程对连接会话进行处理。

一个服务器端--->两个客户端口同时连接 

 

 

一个客户端结束会话时的通信包:

 

 另一个客户端会话结束的通信包

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ TCP网络编程--服务器端多线程处理会话连接 的相关文章

随机推荐

  • 【分享】高精度RTK定位解决方案

    高精度RTK定位系统采用高精度定位标签 xff0c 通过计算机技术 地理信息技术 移动定位技术 通信技术 网络技术 xff0c 为生产现场作业人员配发定位终端 xff0c 实时追踪其位置信息进行相关管控 xff0c 为其活动提供安全技术保障
  • 【分享】5G+北斗RTK高精度人员定位解决方案

    5G 43 北斗RTK高精度定位系统旨在通过5G网络实时提供亚米级 厘米级 毫米级高精度定位服务 xff0c 构建全天候 全天时 全地理的精准时空服务体系 伴随着信息技术日新月异的发展 xff0c 各类 智慧 顺势而出 xff0c 智慧城市
  • 5G+北斗RTK定位:高精度定位技术发展更进一步

    5G 43 北斗RTK定位采用5G定位与北斗RTK定位技术 xff0c 在信号 信息 设施 应用等层面深度融合 xff0c 5G自身可实现亚米级的定位能力与北斗形成信号覆盖互补 xff0c 实现从室内到室外无缝隙衔接与定位 5G通信技术的到
  • 室外定位:高精度北斗RTK定位技术

    北斗RTK定位技术 xff0c 也称北斗差分定位技术 xff0c 利用我国自主研发的北斗卫星定位系统实现精确定位功能 定位精度可根据需要 xff0c 通过选择不同精度的人员定位终端来实现 在科技强国的战略驱动下 xff0c 北斗RTK定位技
  • 【高精度定位】RTK定位与RTD定位知识科普

    高精度定位一般指亚米级别或厘米级别的定位 xff0c 常见的室内有蓝牙AoA和UWB两种技术 xff0c 室外有北斗地基增强技术 xff0c 这些技术都是采用算法进行定位 工业4 0时代 xff0c 在资源和环境约束不断强化的背景下 xff
  • curl http或https上传下载

    curl的使用 注意如果是https请求需要带上ssl的库和curl库如下图 上传文件 回调函数 span class token keyword static span size t span class token function h
  • 层次遍历构建二叉树

    span class hljs keyword struct span TreeNode span class hljs keyword int span val span class hljs keyword struct span Tr
  • Jetson tx2 使用 jetpack 4.3刷机全过程

    1 首先准备一台安装有ubuntu 18 04 ubuntu16 04 系统的主机 xff08 host也就是笔记本 xff09 2 在nvidia官网注册一个nvidia的账号用于下载jetpack 4 3时使用 xff08 刷机过程中需
  • 2020/2/21 Linux Socket编程 高级篇——广播

    广播 xff1a 实现一对多的通信 SO BROADCAST选项 它控制了UDP套接字是否能发广播数据报 xff0c 选项类型是int xff0c 非零表示 是 只有UDP能用 xff0c TCP不能 如果是一个广播地址 xff0c 但SO
  • 大小端字节序(Big Endian和Little Endian)

    那么何为字节序 xff08 Endia xff09 呢 xff1f Big Endian是指低地址存放最高有效字节 xff08 MSB xff09 xff0c 而Little Endian则是低地址存放最低有效字节 xff08 LSB xf
  • GPS定位及通信协议解析

    1 简介 上图为某公司的GPS定位模块 xff0c 自己在使用其进行GPS定位过程中学习到的知识分享给大家 主要参数如下 半双工 UART 3 3V TTL 电平 RS232 IIC CAN 接口输出 xff0c 更快速的应用 xff1b
  • JVM系列(八):堆(Heap)的相关知识介绍

    目录 1 JVM堆的概念 2 JVM堆的特点 3 JVM堆的内部结构 3 1 组成 3 2 堆内存内部空间所占比例 3 3 永久代和元空间区别 4 堆空间的大小设置 5 堆空间垃圾回收 1 JVM堆的概念 JVM中的堆是用来存放对象的内存空
  • C++读写TIF格式

    参考文章 xff1a xff08 1 xff09 https www cnblogs com gywei p 3393816 html xff08 2 xff09 https blog csdn net han jiang xue arti
  • matlab Fourier变换--方波信号的分解与重建

    N 61 200 采用的数据点数 dt 61 4 N 采样的间隔 for n 61 1 N 生成一个方波 if n dt gt 61 2 x n 61 0 8 else x n 61 0 8 end end figure subplot 2
  • matlab 小波分析--高通滤波器和低通滤波器

    xff08 一 xff09 加载一个尺度滤波器 load db8 w 61 db8 figure subplot 4 2 1 stem w title 39 原尺度滤波器 39 计算4个滤波器 Lo D Hi D Lo R Hi R 61
  • C/C++中rand() 函数产生随机数与srand()设置随机数种子

    xff08 1 xff09 rand 产生随机数 xff0c 输出的随机数序列是确定的 xff0c 即每次运行结果一致 include lt iostream gt int main int i j for i 61 0 i lt 10 i
  • matlab与数字图像处理--膨胀和腐蚀

    对于初学者 xff0c 参考一篇很好的说明 xff1a https blog csdn net alw 123 article details 83868878 左边是一个二值化的测试图像 xff0c 白色为图像元素 xff0c 黑色为背景
  • Emmet语法

    Emmet语法 1 1 快速生成HTML结构语法1 2 快速生成CSS样式语法1 3 快速格式化代码 Emmet语法的前身是Zen coding 它使用缩写 来提高html css的编写速度 Vscode内部已经集成该语法 快速生成HTML
  • CString,int,string,char*之间的转换

    C 43 43 标准函数库 中说的 有三个函数可以将字符串的内容转换为字符数组和C string 1 data 返回没有 0 的字符串数组 2 c str xff0c 返回有 0 的字符串数组 3 xff0c copy int 转 CStr
  • C++ TCP网络编程--服务器端多线程处理会话连接

    客户端程序 xff1a include lt winsock h gt include lt iostream gt pragma comment lib 34 ws2 32 lib 34 include lt Windows h gt i