TCP之 select模型

2023-05-16

前记:select模型主要用于解决tcp通信中,每次处理一个独立的客户都要单独的开线程,这样会导致客户连接数很大时,线程数也会很多。而使用select就会将线程缩减至2个,一个主线程用于接收Accept客户端的连接,另外一个子线程用于监听已经连接上来的客户端是否有信号状态,如果有信号则进行相应的消息处理。

服务端:

#include "stdafx.h"
#include <stdio.h>
#include <WinSock2.h>//必须放在windows.h前面
#include <Windows.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")

fd_set g_fdClientSock;
int clientNum = 0;

DWORD WINAPI ListenThreadProc(LPARAM lparam)
{

	fd_set fdRead;
	FD_ZERO(&fdRead);
	int nRet = 0;
	char *recvBuffer = (char*)malloc(1024);
	if (!recvBuffer)
	{
		return -1;
	}
	memset(recvBuffer, 0, 1024);
	while (TRUE)
	{
		fdRead = g_fdClientSock;
		timeval vt;

		vt.tv_sec = 0;
		vt.tv_usec = 0;
		nRet = select(0, &fdRead, 0,0,&vt);//会阻塞检查集合中所有socket是否有信号
		if (nRet != SOCKET_ERROR)
		{
			for (int i=0; i<g_fdClientSock.fd_count; i++)
			{
				if (FD_ISSET(g_fdClientSock.fd_array[i], &fdRead))
				{
					memset(recvBuffer, 0, 1024);
					nRet = recv(g_fdClientSock.fd_array[i], recvBuffer, 1024, 0);
					if (nRet >0)
					{
						//todo:
						printf("接收到数据:%s", recvBuffer);
						send(g_fdClientSock.fd_array[i], recvBuffer, strlen(recvBuffer), 0);
					}
					else//如果接收失败,则从集合中清除响应socket,并把客户端数量减1
					{
						closesocket(g_fdClientSock.fd_array[i]);
						clientNum--;
						FD_CLR(g_fdClientSock.fd_array[i], &g_fdClientSock);
					}
				}
			}
		}
	}

	if (recvBuffer)
	{
		free(recvBuffer);
		recvBuffer=nullptr;
	}
	return 0;
}

void main()
{
	int port = 5099;
	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("Failed to load Winsock");
		return;
	}

	//创建用于监听的套接字  AF_INET:IPV4版本
	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
	if (sockSrv == INVALID_SOCKET)
	{
		return;
	}

	//地址绑定-告诉操作系统是在哪一个地址及端口
	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(port); //1024以上的端口号,htons本地转换为网络数据
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//电脑上所有的网络ip

	int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
	if(retVal == SOCKET_ERROR)
	{
		printf("绑定bind失败:%d\n", WSAGetLastError());
		return;
	}

	if(listen(sockSrv,5/*SOMAXCONN*/) ==SOCKET_ERROR)
	{
		printf("监听listen失败:%d", WSAGetLastError());
		return;
	}

	SOCKADDR_IN addrClient;//用于获取连接上来的人的地址信息
	int len = sizeof(SOCKADDR);

	CreateThread(NULL,NULL, (LPTHREAD_START_ROUTINE)ListenThreadProc, NULL, NULL, NULL);

	while(clientNum < FD_SETSIZE)
	{
		//等待客户请求到来	
		SOCKET clientSock = accept(sockSrv, (SOCKADDR *) &addrClient, &len);
		if(clientSock == SOCKET_ERROR)
		{
			printf("接收Accept失败:%d", WSAGetLastError());
			break;
		}
		else
		{
			printf("接收Accept到客户端IP:[%s]\n", inet_ntoa(addrClient.sin_addr));
		}
		FD_SET(clientSock, &g_fdClientSock);//添加到集合中去
		clientNum++;//每次接收到一个人就+1,目前最多接收64个客户
	}

	closesocket(sockSrv);
	WSACleanup();
	system("pause");
}

客户端:

// Tcp_client.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

void main()
{
	//加载套接字
	WSADATA wsaData;
	char buff[1024];
	memset(buff, 0, sizeof(buff));

	if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("Failed to load Winsock");
		return;
	}

	SOCKADDR_IN addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(5099);//http默认端口
	addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

	//创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
	if(SOCKET_ERROR == sockClient){
		printf("Socket() error:%d", WSAGetLastError());
		return;
	}

	//向服务器发出连接请求
	if(connect(sockClient, (struct  sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET){
		printf("Connect failed:%d", WSAGetLastError());
		return;
	}

	int iRecvLen = 0;

	//发送数据
	char* buffSend = "hello, this is a Client....";
	iRecvLen = send(sockClient, buffSend, strlen(buffSend), 0);
	
	
	//接收数据
	iRecvLen = recv(sockClient, buff, sizeof(buff), 0);
	printf("%s\n", buff);

	//关闭套接字
	closesocket(sockClient);
	WSACleanup();
	system("pause");
}

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

TCP之 select模型 的相关文章

  • Go TCP 读取是非阻塞的

    我正在尝试用 Go 创建服务器和客户端 我已经成功地与服务器和客户端进行通信 但我遇到的问题是golang中的TCP读取是非阻塞的 我想知道 golang 中的读取是否有可能像 C 中的读取一样阻塞 谢谢 EDIT 这是服务器的源代码 fu
  • Web 服务器可以处理多少个套接字连接?

    假设我要获得共享 虚拟或专用托管 我在某处读到服务器 计算机一次只能处理 64 000 个 TCP 连接 这是真的吗 无论带宽如何 任何类型的托管可以处理多少个 我假设 HTTP 通过 TCP 工作 这是否意味着只有 64 000 个用户可
  • 两个http请求可以合并在一起吗?如果可以的话,nodeJS服务器如何处理呢?

    昨天我做了一些关于 NodeJS 的演讲 有人问我以下问题 我们知道nodeJS是一个单线程服务器 多个请求是 到达服务器并将所有请求推送到事件循环 如果什么 两个请求同时到达服务器 服务器将如何处理 处理这种情况 我猜到了一个想法并回复如
  • C# Socket.receive连续接收0字节且循环中不阻塞

    我正在尝试用 C 编写一个最简单的多线程 TCP 服务器 它接收来自多个客户端的数据 每次连接新客户端时 都会建立套接字连接 并将套接字作为参数传递给新类函数 之后运行 while 循环并接收数据 直到客户端连接为止 这里的问题是 sock
  • 发起TCP连接关闭后如何接收数据?

    TCP 允许一侧发出 FIN 并让另一侧在结束其一侧的连接之前响应一些数据 我如何使用 NET 来实现这一点TcpClient 看来我必须使用Close发出FIN 但之后我不能再打电话Client Receive since Client被
  • 为什么turn服务器不支持tcp连接?

    我是 WebRTC 新手 我需要为我的 webrtc 应用程序配置我自己的 Turn 服务器 我使用以下命令安装了我的转弯服务器 apt get install coturn 我只需要通过 tcp 运行转变服务器 它不必使用 UDP 进行任
  • 自动打开命名管道和 tcp\ip

    我正在安装一个需要修改 SQL Server 的新产品 具体来说 启用 tcp ip 并打开命名管道 我知道如何手动完成 我想要的是一种通过 SQL 或 C 代码为新客户自动化执行此操作的方法 我希望有任何关于正确方向的建议 您可以使用 C
  • 选择不带 FROM 但有多于一行的选择

    如何在不从现有表中进行选择的情况下生成 2 行 2 列的表 我正在寻找的是一个返回的选择语句 e g id value 1 103 2 556 Use UNION http dev mysql com doc refman 5 0 en u
  • 我应该害怕使用 UDP 进行客户端/服务器广播通话吗?

    我在过去的两天里阅读了每一篇StackOverflow问题和答案 以及googling当然 关于印地TCP and UDP协议 以便决定在我的用户应用程序和 Windows 服务之间的通信方法中应该使用哪一种 从我目前所看到的来看 UDP是
  • 访问 AWS 上的 Tensorboard

    我正在尝试访问 AWS 上的 Tensorboard 这是我的设置 张量板 tensorboard host 0 0 0 0 logdir train 在端口 6006 上启动 TensorBoard b 39 您可以导航到http 172
  • 无法分配请求的地址 - 可能的原因?

    我有一个由主服务器和分布式从服务器组成的程序 从属服务器向服务器发送状态更新 如果服务器在固定时间内没有收到特定从属服务器的消息 则会将该从属服务器标记为关闭 这种情况一直在发生 通过检查日志 我发现从站只能向服务器发送一个状态更新 然后永
  • MySql JOINS 的优点/缺点

    当我从多个表中选择数据时 我经常使用 JOINS 最近我开始使用另一种方式 但我不确定从长远来看会产生什么影响 例子 SELECT FROM table 1 LEFT JOIN table 2 ON table 1 column table
  • VB SQL 语句未选择正确的行

    我试图使用 SELECT 语句在我的数据库中 选择 一个人 但它没有选择正确的人 我也不确定为什么 我正在使用访问数据库 数据库连接代码 Imports System Data OleDb Module Database Connectio
  • TcpClient 在异步读取期间断开连接

    我有几个关于完成 tcp 连接的问题 客户端使用 Tcp 连接到我的服务器 在接受客户端后listener BeginAcceptTcpClient ConnectionEstabilishedCallback null 我开始阅读netw
  • 使用 boost 异步发送和接收自定义数据包?

    我正在尝试使用 boost 异步发送和接收自定义数据包 根据我当前的实现 我有一些问题 tcpclient cpp include tcpclient h include
  • MySQL - 选择一行 - 然后相对于所选行的下一个和上一个

    我会尽力澄清这一点 我需要在不使用 id 的情况下选择特定行和该选定行的前一个相对行以及该选定行的下一个相对行 这可能吗 简而言之 上一篇和下一篇 我不能 也许我只是不知道如何 使用 id 的原因是因为它们不是按顺序排列的 正如您从这个相当
  • Erlang gen_tcp 连接问题

    简单的问题 这段代码 client gt SomeHostInNet localhost to make it runnable on one machine ok Sock gen tcp connect SomeHostInNet 56
  • 如何在Linux内核源代码中打印IP地址或MAC地址

    我必须通过修改 Linux 内核源代码来稍微改变 TCP 拥塞控制算法 但为了检查结果是否正确 我需要记录 MAC 或 IP 地址信息 我使用 PRINTK 函数来打印内核消息 但我感觉很难打印出主机的MAC IP地址 printk pM
  • 如何重新加载 jquery dropkick 对象

    我使用一个简单的选择列表和 jquery dropkick 库来使其美观 现在我想在更改相应的选择元素后更改 dropkick 内容 出现了一个新选项 但只需调用 select dropkick 不起作用 而且好像不支持 只需从头开始重建那
  • 从表中选择行,其中另一个表中具有相同 id 的行在另一列中具有特定值

    在 MySQL 中 如果我们有两个表 comments key value 1 foo 2 bar 3 foobar 4 barfoo and meta comment key value 1 1 2 1 3 2 4 1 我想得到来自以下人

随机推荐

  • matlab 画图时遇到的一些问题以及解决方法

    matlab 画图时遇到的一些问题以及解决方法 最近在使用 matlab 画图时 xff0c 遇到了许许多多各式各样的问题 xff0c 有些问题甚至折腾了很久才搞好 xff0c 特此记录下来 设置画图时图中线段的粗细plot x1 y1 3
  • Ubuntu18.04上Gazebo安装和使用

    一 基本介绍 Gazebo是一款与机器人开发相关的3D动态模拟仿真软件 xff0c 能够在复杂的室内和室外环境中准确有效地模拟机器人群 这款软件中包含了丰富的机器人模型 xff0c 环境库以及各种各样的传感器 xff0c 并且在操作方面它的
  • Python运行 import cv2 等报错 Illegal instruction (core dumped) 解决办法

    import cv2 报错 Illegal instruction core dumped nanopc T4 开发板上安装好 opencv 后 xff0c import cv2 时 会报错 Illegal instruction core
  • 多个py文件同时执行(多进程与多线程实现)

    本人在编写python程序时 xff0c 需要多个py文件在不同终端内同时运行 xff0c 从而配合实现某种功能 xff0c 经过多方查找与实验 xff0c 排除了很多无法使用的方案 xff0c 最终确定了以下两个方案 xff0c 现将其记
  • nanopc-T4 开发板通过USB麦克风采集录制音频

    文章目录 1 使用 nanopc T4 开发板采集音频2 使用 Tyless外置usb麦克风录制声音3 使用 ffrmpeg 将实时视频与音频合并并推流到 rtmp 服务器中4 成功实现opencv采集图像与音频合并推送到rtmp 1 使用
  • 北京超级云计算中心操作训练指南

    北京超级云计算中心操作指南 本人在实验室做深度学习图像领域相关研究 xff0c 前期使用实验室的设备 2080Ti xff0c 运行时间较慢 xff1b 跑一轮需要6个小时以上 xff1b 后来开始使用超算 xff0c 运行速度比实验室快多
  • windows to go 和 linux to go 制作教程

    文章目录 使用 ventoy 制作windows to go 和 linux to go 教程 xff0c 将系统装进U盘中随身携带1 ventoy 介绍2 准备工作3 windows to go3 1 将 U盘初始化3 2 虚拟磁盘安装
  • 使用nps搭建内网穿透并配置泛域名解析

    使用nps搭建内网穿透并配置泛域名解析 前言1 准备工作2 服务器端搭建nps并配置2 1 配置nps配置文件2 2 docker安装nps2 3 web端配置nps并使用 3 客户端使用nps4 配置泛域名解析5 参考链接 前言 nps是
  • web内外网判断界面

    因日常需要 xff0c 我们在实验室内网中部署了一个服务 xff0c 在校园网内都能正常访问 xff0c 同时配置了内网穿透服务 xff0c 实现外网也能正常访问 但外网访问毕竟是通过内网穿透实现 xff0c 稳定性与网速都有限制 xff0
  • 为无登陆鉴权功能的接口与网站添加登陆鉴权功能

    1 缘由 本人部分服务的测试接口为方便日常测试调试 xff0c 使用了 ip 43 端口 的形式进行访问 xff0c 并且未配置账号密码鉴权机制 在日常测试一段时间后 xff0c 终于还是收到了来自腾讯云的监管通知 xff0c 说服务存在数
  • RoboMaster机器人运行教程(一)

    1 环境配置 系统 xff1a ubuntu16 04 xff0c 安装ROS 2 基础学习 需要C 43 43 和python基础 xff0c 和ROS的基础知识 xff0c 网上有很多教程 xff0c 推荐知乎大佬教程 xff1a 我的
  • slambook2+ch7+pose_estimation_2d2d+估计多张图像之间的位姿

    算法 计算第一张图和第二张图的关键点并匹配以第一张图的相机坐标为世界坐标 xff0c 计算第二张图相对第一张图的旋转矩阵 平移矩阵不断更新第一张图 xff0c 在进行第二次计算时 xff0c 以第二张图为第一张图 xff0c 以第二张图的相
  • 重做Unbuntu 18.0.43 LTS系统 并为SLAM配置环境

    目录 前言 一 安装列表 1 Ubuntu 18 0 43 LTS 1 0 A 搜狗输入法 1 0 B ibus输入法安装 1 1 更换软件源 1 2 安装vim curl等工具 1 3 安装浏览器Chrome git等 1 4 安装g 4
  • PostMan各个版本下载

    打开地址 xff1a https gitee com hlmd PostmanCn
  • 快速解决matlab出现错误使用mex,未找到支持的编译器或 SDK的提示

    matlab mex命令提示找不到编译器或SDK 参考博客 xff1a https blog csdn net cfqcfqcfqcfqcfq article details 63295746 utm source 61 blogxgwz1
  • linux 串口应用层API

    include lt termios h gt struct termios oldtio newtio fd 61 open dev tty0 O RDWR O NOCTTY tcgetattr fd amp oldtio 获取终端参数
  • 2022年中国研究生数学建模竞赛B题-方形件组批优化问题

    一 背景介绍 智能制造被 中国制造2025 列为主攻方向 而个性化定制 更短的产品及系统生命周期 互联互通的服务模式等成为目前企业在智能制造转型中的主要竞争点 以离散行业中的产品为例 xff0c 如电子器件 汽车 航空航天零部件等 xff0
  • 无线网络知识、WiFi原理

    无线网络 B站链接 一 电磁波的传输 电磁波传播方式 地波 xff08 低于2MHZ xff09 天波 2MHZ 30MHZ 直线波 30MHZ以上 电磁波的发射与接收装置 天线 作用 xff1a 将电磁波辐射到空间中或收集电磁波 辐射模式
  • yolov5输出检测到的目标坐标信息

    找到detect py文件 span class token keyword for span span class token operator span xyxy span class token punctuation span co
  • TCP之 select模型

    前记 xff1a select模型主要用于解决tcp通信中 xff0c 每次处理一个独立的客户都要单独的开线程 xff0c 这样会导致客户连接数很大时 xff0c 线程数也会很多 而使用select就会将线程缩减至2个 xff0c 一个主线