59 Linux socket的select编程

【Linux】多路IO复用技术①——select详解&如何使用select模型实现简易的一对多服务器(附图解与代码实现) 这一篇的篇幅可能有点长,但真心希望大家能够静下心来看完,相信一定会有不小的收获。那么话不多说,我们这就开始啦!!! 阅读详情

59.1 引言

        作为代码搬运工,正常来说写过一次代码之后,就不想重新的重复造轮子,所以特此记录,Linux下的socket的select编程相关配置及例程。

59.2 例程

        Linux socket例程。



int ht_socketOpen(void)
{
	int		ni				= 0;
	int		ret				= 0;
	int		sock_fd			= 0;
	int 	optval			= 0;
	int		sock_nbio		= 1;
	int 	keep_alive 		= 1;
	int 	isIPAddrFlag	= 0;
	int rcvBufSize 			= (4*1024);
	int rcvBufSizelen 		= sizeof(rcvBufSize);

	struct addrinfo		*res = NULL;
	struct addrinfo		hints;
	struct sockaddr_in 	local_ipv4;
	struct sockaddr_in 	server_ipv4;
	struct ql_data_call_info info = {0};

	if(gsock_fd >0)
	{
		Console_Error("socket is already opened\r\n");
		return gsock_fd;
	}
	
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family 	= AF_INET;
	hints.ai_socktype 	= SOCK_STREAM;

	//创建tcp套接字
	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(sock_fd < 0)
	{
		Console_Error("open socket failed\r\n");
		goto iExit;
	}
	
	//保存打开的socket
	gsock_fd = sock_fd;

	//设置接受缓冲区大小
	ret = setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, sizeof(rcvBufSize));
	if(ret < 0)
	{
		Console_Error("setsockopt SO_RCVBUF failed\r\n");
		goto iExit;
	}
	//获取系统修改后的大小
	ret = getsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, (socklen_t*)&rcvBufSizelen);
	if(ret < 0)
	{
		Console_Error("getsockopt SO_RCVBUF failed\r\n");
		goto iExit;
	}


	//设置接收阻塞时间
	optval	= 1000;
	ret = setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &optval, sizeof(optval));
	if (ret < 0) 
	{
		Console_Error("setsockopt SO_RCVTIMEO failed\r\n");
		goto iExit;
	}

	optval = 1;
	ret = setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
	if (ret < 0) 
	{
		Console_Error("setsockopt TCP_NODELAY failed\r\n");
		goto iExit;
	}

	//设置链接为keepalive类型
	ret = setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keep_alive, sizeof(keep_alive));
	if(ret < 0)
	{
		Console_Error("setsockopt SO_KEEPALIVE failed\r\n");
		goto iExit;
	}

	optval = 180;
	if (setsockopt(sock_fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval)) < 0) {
		Console_Error("setsockopt TCP_KEEPIDLE failed\r\n");
		goto iExit;
	}

	/* Send next probes after the specified interval. Note that we set the
	 * delay as interval / 3, as we send three probes before detecting
	 * an error (see the next setsockopt call). */
	optval = 60;
	if (setsockopt(sock_fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(optval)) < 0) {
		Console_Error("setsockopt TCP_KEEPINTVL failed\r\n");
		goto iExit;
	}

	/* Consider the socket in error state after three we send three ACK
	 * probes without getting a reply. */
	optval = 3;
	if (setsockopt(sock_fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval)) < 0) {
		Console_Error("setsockopt TCP_KEEPCNT failed\r\n");
		goto iExit;
	}

    memcpy(serverIP, "192.168.0.163", strlen("192.168.0.163"));
    targetPort  = 12584;

	//获取本地ip相关信息
	ql_get_data_call_info(HT_PROFILE_IDX, HT_IP_PROTOCOL, &info);
	local_ipv4.sin_family = AF_INET;
	local_ipv4.sin_port = htons(ql_soc_generate_port());
	local_ipv4.sin_addr = info.v4.addr.ip;

	//绑定端口和ip
	ret = bind(sock_fd,(struct sockaddr *)&local_ipv4,sizeof(struct sockaddr));
	if(ret<0)
	{
		Console_Error("bind cid[%d] failed(ip %s)\n", HT_PROFILE_IDX,inet_ntoa(local_ipv4.sin_addr));
		goto iExit;
	}

	//复制信息以
	server_ipv4.sin_family 		= AF_INET;
	server_ipv4.sin_addr.s_addr	= inet_addr(serverIP);
	server_ipv4.sin_port 		= htons(targetPort);
	
	//连接服务器
	ret = connect(sock_fd, (struct sockaddr *)&server_ipv4, sizeof(server_ipv4));
	if(ret < 0)
	{
		inet_ntop(AF_INET,&server_ipv4.sin_addr, serverIP, 16);
		Console_Error("connect %s:%d failed\r\n",serverIP,server_ipv4.sin_port);
		goto iExit;
	}

	Console_Debug("connect %s success!\r\n",serverIP);

	//释放资源
	if(res!=NULL)
		freeaddrinfo(res);
	
	return 0;
iExit:
	if(sock_fd>0)
	{
		gsock_fd = 0;
		close(sock_fd);
	}

	//释放资源
	if(res!=NULL)
		freeaddrinfo(res);

	return -1;
}

select例程。


int ht_socketSend(uint8_t *pBuffer, uint16_t nlength, int timeoutMs)
{
	int ret 	= 0;
	int sock_fd = -1;
	struct timeval t;
	fd_set write_fds;

	sock_fd = gsock_fd;	
	
	if(sock_fd <= 0)
	{
		Console_Error("socket %d error\r\n",sock_fd);
		return -1;
	}
	
	t.tv_sec	= 1;
	t.tv_usec	= timeoutMs*1000;

	FD_ZERO(&write_fds);
	FD_SET(sock_fd, &write_fds);

	ret = select(sock_fd + 1, NULL, &write_fds, NULL, &t);
	if(ret < 0)
	{
		Console_Error("select failed!,ret:%d\r\n",ret);
		return -1;
	}
	
	if(FD_ISSET(sock_fd, &write_fds))
	{
		ret = send(sock_fd, pBuffer, nlength, 0);
		if(ret > 0)
		{
			return ret;
		}
		else
		{
			return -1;
		}
	}

	return -1;
}

int ht_socketRcv(uint8_t *pBuffer, uint16_t nlength, int timeoutMs)
{	
	int ret 		= 0;
	int sock_fd 	= -1;
	int readSize 	= 0;
	struct timeval t;
	fd_set read_fds;

	sock_fd = gsock_fd;	

	if(sock_fd <=0)
	{
		Console_Error("socket %d error\r\n",sock_fd);
		return -1;
	}

	do
	{
		t.tv_sec	= 0;
		t.tv_usec	= 1000; //ms阻塞
		FD_ZERO(&read_fds);
		FD_SET(sock_fd, &read_fds);

		ret = select(sock_fd + 1, &read_fds, NULL, NULL, &t);
		if(ret < 0)
		{
			Console_Error("select failed!,ret:%d\r\n",ret);
			return -1;
		}
		
		if(FD_ISSET(sock_fd, &read_fds))
		{
			ret = recv(sock_fd, (uint8_t*)(pBuffer+readSize), nlength , 0);
			if(ret > 0)
			{
				readSize += ret;
				//数据读完了
				if(readSize == nlength)
				{
					break;
				}
			}
			else if(ret == 0)
			{
				Console_Error("rcv occur error\r\n");
				break;
			}
		}

		if(timeoutMs >=1 )
			timeoutMs--;

	}while(timeoutMs>0);
	
	return readSize;
}

SpringSecurity(15)——OAuth2密码模式 SpringSecurity Oauth2密码模式 阅读详情

相关推荐

Matlab实战:3种雷达间歇采样干扰的仿真与识别(附完整代码)

本文通过Matlab实战,详细仿真了雷达有源间歇采样干扰的三种核心样式:直接转发、重复转发和循环转发干扰。文章提供了完整的代码实现,并深入探讨了基于时频分析和循环平稳分析的特征提取与识别方法,为雷达抗干扰技术的学习与实践提供了清晰的工程实现路径。

weixin_29053695的博客 364

Linux socket编程(6):IO复用之select原理及例子

在之前的网络编程中,我们遇到了一个问题:客户端需要一边监听来自stdin的键盘输入,一边监听来自服务端的消息服务端要一边获取来自客户端的消息,一边accept新的设备连接也就是我们希望在一个或多个I/O条件准备就绪时,能够得到通知。在前面的文章中,我们使用Linux中的fork。但在Linux中还有一个I/O多路复用的概念,它由select和poll函数实现,这篇文章就来介绍一下多路复用的概念。

主要分享嵌入式软件、人工智能部分知识 1782

Ubuntu1804 关于ubuntu18.04下载软件仓库信息失败,请检查网络连接 的解决方案

今天电脑在更换软件源的时候遇到了这个问题。出现了如上图所示的错误信息。 尝试了各家优快云的博客之后,发现方法大同小异,均无法解决。 方法大多都是要求更换软件源,如下所示: 打开“Ubuntu软件中心”-->点击“编辑”-->点击“软件源”-->在Ubuntu软件界面,“下载自”默认是“中国的服务器”,改为“主服务器”试试 2.打开更新管理器-》设置-》选择站点-》...

weixin_43729409的博客 1万+

【Linux系统与网络编程】18:并发模型

本文介绍了常见的服务器并发模型及其演进过程,包括多进程、多线程以及多种反应堆模式。重点分析了单反应堆、单反应堆+线程池、主从反应堆和主从反应堆+线程池等架构特点,并详细展示了线程池的C语言实现代码。线程池实现包含任务队列管理、工作线程调度、线程动态调整等功能,通过互斥锁和条件变量确保线程安全。该文为服务器高并发设计提供了从基础到进阶的完整技术方案参考。

https://blog.youkuaiyun.com/m0_74834215 752

Agent 长期记忆三代演进:从 RAG 到 Memory Graph,mem0 / Zep / LangMem / Letta 深度横评

文章摘要 2026年,Agent长期记忆技术迎来关键突破,OpenAI、Anthropic等厂商通过扩大上下文窗口和推出记忆工具,推动长期记忆从工程补丁发展为独立技术层。本文通过分析三代记忆架构演进(RAG→结构化Fact→MemoryGraph)和四大方案(mem0/Zep/LangMem/Letta)的8维度横评,揭示以下核心观点: 长上下文≠长期记忆:128K上下文如同RAM,仍需硬盘式记忆层筛选和结构化存储,避免“Context Rot”导致的准确率下降。 三代架构演进: Gen1(RAG):向量检

LDZKKJ的博客 1423

ubuntu通过qemu安装银河麒麟V10_Arm_v8 (kylin_v10_飞腾/鲲鹏版)

一、windows下安装vmware虚拟机 二、ubuntu下载地址 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/20.04/ubuntu-20.04.3-live-server-amd64.iso 三、vmware中新建虚拟机,并使用ubuntu-20.04.3-live-server-amd64.iso作为启用盘 。。。在虚拟机中安装ubuntu(略) 四、配置ssh(如果ssh登录不上时配置) 修改openssh的配置 vi /etc/s

u010533742的博客 8704

Linux网络编程socket错误分析

<br />socket错误码:<br /> <br />EINTR: 4<br />阻塞的操作被取消阻塞的调用打断。如设置了发送接收超时,就会遇到这种错误。<br />只能针对阻塞模式的socket。读,写阻塞的socket时,-1返回,错误号为INTR。另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。如果recv的返回值为0,那表明连接已经断开,接收操作也应该结束。<br /> <br />ETIMEOUT:110<br />1、操作超时

jaylong35的专栏 5085

手把手教你学SIMULINK模块库文件专栏-From Workspace 模块详解

模块是 Simulink 中的一个信号源模块,用于从 MATLAB 工作区加载数据作为输入信号。该模块允许用户将预先在 MATLAB 中生成的数据(如时间序列、矩阵或结构体)导入到 Simulink 模型中,从而实现更灵活的信号输入和仿真控制。通过深入了解其参数的影响及结合 MATLAB 脚本的应用,读者可以更加有效地利用这一模块进行仿真和研究。此外,通过实际应用场景的扩展以及常见问题解答部分的帮助,能够更好地掌握。模块是一个非常灵活的工具,适用于需要从 MATLAB 工作区加载数据的各种场景。

MHD0815的博客 633

基于python实现的内网穿透工具 (proxynt)

1. 随时随地打开浏览器管理端口映射 2. 公网服务器和内网客户端之间使用 WebSocket 加密传输 3. 依赖少, 使用 pip一键安装 4. 稳定, 自动重连, 已在生产环境中使用

wktadmin 7494

VMware16虚拟机:下载和安装教程

VMware16 虚拟机 下载和安装教程

MQ0522的博客 20万+

掌握 Unity 中的状态机:综合指南

最后,将拥有一个由状态机驱动的功能齐全的播放器控制器,可以集成到自己的项目中。此外,状态机有助于实现复杂的人工智能、玩家控制、动画系统等,从而形成更强大、更灵活的游戏架构。状态机是计算机科学和游戏开发中的一个基本概念,它通过定义一组有限的状态及其之间的转换来模拟实体的行为。你可以定义常见的状态行为,例如 Enter、Update 和 Exit 方法,确保整个状态机架构的一致性和连贯性。由于前面提到的状态类扩展了 BaseState 类,因此我们可以为具有不同状态的不同对象创建单独的类。

yolo模型训练找我,AI游戏合作找我 1453

LINUX|深入学习linux socket编程之select

深入学习linux socket编程之select

编程改变世界。想做一些改变世界的产品。感谢一键三连。 458

2026年运维工程师常见面试选择题

这篇文章总结了30道Linux运维面试常见问题及解析,涵盖基础命令、系统监控、故障排查、数据库、缓存、容器编排等多个方面。主要内容包括: 基础命令使用:如df查看磁盘、free查看内存、top监控进程等 系统监控与故障排查:负载判断、端口检查、进程管理等 中间件相关:Nginx状态码、MySQL主从复制、Redis缓存问题 容器技术:Docker优势、Kubernetes作用 运维理念:高可用、监控告警、发布策略、备份容灾 工作原则:故障处理优先级、运维工程师核心能力 文章不仅提供标准答案,还解析了各命令的

不务正业的猿 193

Linux下网络socket编程——实现服务器(select)与多个客户端通信

一、关于socket通信 服务器端工作流程: 调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址绑定 调用listen()函数监听socket() 函数创建的套接字,等待客户端连接 当客户端请求到来之后 调用 accept()函数接受连接请求,返回一个对应于此连接的新的套接字,做好通信准备 调用 write()/read() 函数和 s...

sinat_35297665的博客 1074

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

socket 通信之select

  对于socket 通信,大家很多都用的单线程通信。同时只能监听一个端口,只能响应一个服务,select的方式可以解决多个socket 被连接的问题。一次可以分配多个资源,只要一个连接便可以进行通信。在网络已经有很多的select 的例子。不过很多例子没有真正体现到select的精妙之处。此函数主要是对多个文件描述符进行监听,直到某一个或者多个被连接。   首先我们介绍fd_set这...

awei1976的博客 303

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

linux网络编程之socket(十三):epoll 系列函数简介、与select、poll 的区别

一、epoll 系列函数简介 #include int epoll_create(int size); int epoll_create1(int flags); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event

Meditation 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

linux网络编程之socket(十一):套接字I/O超时设置方法和用select实现超时

一、使用alarm 函数设置超时  C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13 void handler(int sig) { } signal(SIGALRM, handler); alarm(5); int ret = read(fd, buf, sizeof(b

Meditation 9187

在python中编写socket服务端模块(一):使用select

在linux上编写socket服务端程序一般可以用select、poll、epoll三种方式,本文主要介绍使用select编写socket服务端模块与客户端模块。   服务器端程序代码:     ? 1 2 3 4 5 6 7 8 9 10 11 12 13 1

超纯的小白兔 1612

linux下socket编程记录

最近要做一个linux下的socket程序用于测试网络连接,基于TCP,我做的是一个放到嵌入式设备里的客户端,向windows服务器发送消息。一路跌跌撞撞走来还没到头,现在把期间遇到的问题记录下来以便查阅。为了方便我用了虚拟机编译程序,windows下编写程序,然后通过共享windows下的源文件到linux下编译,但是在linux下直接编译挂载的源程序时提示出错/usr/bin/ld:canno...

weixin_34062329的博客 125

Linux IO复用模型之select

select函数 #include #include int select (int maxfd , fd_set *readset ,fd_set *writeset, fd_set *exceptionset , const struct timeval * timeout); 返回:就绪描述字的正数目,0——超时,-1——出错   参数解释: max

业精于勤而荒于嬉,行成于思而毁于随。 1245

linux socket 聊天室

linux socket 聊天室,本来这并不是我自己要做的,只是为了帮别人完成作业。刚好最近这段时间的课是关于socket编程,何不拿来练练手? 基于socket的聊天室早在开学初就有做过类似的,只不过当时用的java来实现,而且因为没有正式学过socket,代码只是搬用别人的,并没有深入理解。 单用户-服务的对话还是很好实现的,即使是多用户-服务,只要不是连续服务,服务端还是可以通...

dfv6403的博客 293

Linux高并发网络编程开发——tcp状态转换-select-poll

在学习Linux高并发网络编程开发总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。 10-Linux系统编程-第12天(tcp状态转换-select-poll) 一、学习目标 1、能够描述TCP通信过程中主要状态 2、独立使用select实现IO多路转接 3、理解使用poll实现IO多路转接操作流程 二、复习 (上篇是客户端主动断开...

Alliswell_WP 348

Linux socket 多用户

最近一个项目需要socket多用户连续性链接。以前的都是单用户,简单,自己也没有深入了解,这边博客给我了很多启发,谢谢。如果大家有想法可以留言互相讨论、 单用户-服务的对话还是很好实现的,即使是多用户-服务,只要不是连续服务,服务端还是可以通过轮询的方式服务多个用户。问题就在于,常用socket I/O函数大都是阻塞的,这就意味着,单个线程只能服务于一个用户。于是自然而然的想到用多线程,然而多线

~租房的蜗居人~ 680

多路复用poll实现网络socket服务器

文章目录poll函数多路复用poll实现网络socket服务器的编程 poll函数 poll是Linux中的字符设备驱动中的一个函数,poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个...

makunIT的博客 686
上一篇: 58 ESP32 OTA升级(双OTA分区无factory APP)
下一篇: 60 无键值Json数组和有键值json数组实验
Chasing_Chasing
博客等级 码龄10年 233粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值