利用select实现服务器和客户端的随时收发

2023-05-16

服务器代码实现: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#define IP "192.168.8.117"
#define PORT 8888
#define ERR_MSG(msg) do{\
	fprintf(stderr,"__%d__:",__LINE__);\
	perror(msg);\
}while(0)
int main(int argc, const char *argv[])
{
	int sfd=socket(AF_INET,SOCK_STREAM,0);

	int reuse=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速重用\n");
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);

	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
		ERR_MSG("bind");
		return -1;
	}
	
	if(listen(sfd,128)<0){
		ERR_MSG("listen");
		return -1;
	}
	printf("服务器监听成功\n");
	struct sockaddr_in cin;
	struct sockaddr_in arr[1024-4];
	socklen_t addrlen=sizeof(sin);
	
	//创建一个集合
	fd_set readfds;
	fd_set tempfds;
	//清空集合
	FD_ZERO(&readfds);
	FD_ZERO(&tempfds);
	//将需要的文件描述符添加到集合中
	FD_SET(0,&readfds);
	FD_SET(sfd,&readfds);
	//存储最大文件描述符
	int maxfd=sfd;
	int newfd;
	char buf[128]="";
	size_t len=sizeof(buf);
	int s_res;
	int res;
	int k=0;
	while(1){
		tempfds=readfds;
		s_res=select(maxfd+1,&tempfds,NULL,NULL,NULL);
		if(s_res<0){
			ERR_MSG("select");
			return -1;
		}
		//运行到这,说明产生了事件,遍历集合判断是哪个文件描述符产生的事件
		for(int i=0;i<=maxfd;i++){
			//从0开始判断,判断i这个文件描述符是否在集合中,不在则继续遍历
			if(0==(FD_ISSET(i,&tempfds))){
				continue;
			}
			if(0==i){
				printf("发送成功\n");
				fgets(buf,sizeof(buf),stdin);
				buf[strlen(buf)-1]=0;
				send(newfd,buf,sizeof(buf),0);
			}else if(sfd==i){
				printf("触发客户端连接\n");
				newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
				//将每次获取到的信息结构体存储到数组中,newfd从4开始,把他存入数组第一个元素中
				arr[newfd-4]=cin;
				printf("%s %d:连接成功 newfd=%d\n",inet_ntoa(arr[newfd-4].sin_addr)\
						,ntohs(arr[newfd-4].sin_port),newfd);
				//将新生成的newfd添加到集合中
				FD_SET(newfd,&readfds);
				//更新maxfd
				maxfd=maxfd>newfd?maxfd:newfd;
			}else{
				printf("触发客户端交互\n");
				bzero(buf,sizeof(buf));
				res=recv(i,buf,len,0);
				if(res<0){
					ERR_MSG("recv");
					return -1;
				}else if(0==res){
					printf("newfd=%d 客户端关闭\n",i);
					//关闭对应的文件描述符,并将其从集合中清除
					close(i);
					FD_CLR(i,&readfds);
					//清除之后,应寻找在除了i的集合中,最大的文件描述符,并对maxfd重新赋值
					for(int j=maxfd;j>0;j--){
						if(FD_ISSET(j,&readfds)){
							maxfd=j;
							//判断客户端是否全部关闭,全部关闭则退出程序
							if(j==sfd){
								close(sfd);
								return 0;
							}
							break;
						}
					}	
				}else{
					//此时i代表的就是产生事件的newfd
					printf("%s %d newfd:%d:%s\n",inet_ntoa(arr[i-4].sin_addr),\
							htons(arr[i-4].sin_port),i,buf);
				}
			}
		}
	}
	return 0;
}

 客户端代码实现:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#define IP "192.168.8.117"
#define PORT 8888
#define ERR_MSG(msg) do{\
	fprintf(stderr,"_%d_:",__LINE__);\
	perror(msg);\
}while(0)
int main(int argc, const char *argv[])
{
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("sfd");
		return -1;
	}
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_addr.s_addr=inet_addr(IP);
	sin.sin_port=htons(PORT);
	socklen_t addrlen=sizeof(sin);
	if(connect(sfd,(struct sockaddr*)&sin,addrlen)<0){
		ERR_MSG("connect");
		return -1;
	}
	printf("连接服务器成功\n");
	fd_set readfds;
	fd_set tempfds;
	FD_ZERO(&readfds);
	FD_SET(sfd,&readfds);
	FD_SET(0,&readfds);
	int maxfd=sfd;
	char buf[128]="";
	bzero(buf,sizeof(buf));
	while(1){
		tempfds=readfds;
		if(select(sfd+1,&tempfds,NULL,NULL,NULL)<0){
			ERR_MSG("select");
			return -1;
		}
		//判断终端输入事件发生
		if(FD_ISSET(0,&tempfds)){
			scanf("%s",buf);
			//终端输入quit,则客户端退出
			if(0==strcmp(buf,"quit")){
				break;
			}
			send(sfd,buf,sizeof(buf),0);
			printf("发送成功\n");
			bzero(buf,sizeof(buf));
		}
		//判断服务器交互事件发生
		if(FD_ISSET(sfd,&tempfds)){
			if(0==recv(sfd,buf,sizeof(buf),0)){
				printf("服务器关闭\n");
				break;
			}
			printf("接收到:%s\n",buf);
			bzero(buf,sizeof(buf));
		}
	}
	close(sfd);
	return 0;
}

如果客户端终端输入quit,客户端退出。

服务器检测到所有客户端断开连接,则服务器端退出。

服务器端断开连接,则客户端也退出。

效果展示: 

 

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

利用select实现服务器和客户端的随时收发 的相关文章

  • 解决C&C++头文件互相包含问题

    案例说明 xff1a test1中需要调用test2中的go test2 xff0c test2中需要调用test1中的go test1 main cpp span class token macro property span class
  • C++类库开发详解

    前言 xff1a 这是一篇总结性的文章 xff0c 需要有一点C 43 43 和dll基本知识的基础 xff0c 在网上查阅了很多资料感觉没有一篇详细 具体 全面的dll开发介绍 xff0c 我这是根据最近项目和网上资料整理出来的 xff0
  • ROS下建立工作空间以及编译一个包

    在ROS层面上编写软件 xff0c 需要有相关的工作空间 xff08 workspace xff09 生成工作控件并不复杂 xff0c 首先 xff0c 我们打开一个控制台 xff08 Ctrl 43 Alt 43 T xff09 xff0
  • python socket小结

    Python socket 简单编程小结 首先创建服务器端的socket socket server import socket 定义变量 HOST 61 34 localhost 34 PORT 61 是数字类型 xff0c 不是字符串类
  • STM32 IO口模拟I2C+驱动MPU6050

    一年前写的博客 xff0c 没有把驱动代码分享出来是我疏忽了 xff0c 可以到网盘下载驱动代码 链接 xff1a https pan baidu com s 1SDVQfyoOoycCY 6eSXamlQ 密码 xff1a ipj7 之后
  • git常用操作(branch tag)

    git日常总结 1 初次在本地下载分支代码操作2 初次下载远程代码3 创建分支3 1 创建本地分支3 2创建远程分支 4 删除分支4 1 删除本地分支4 2删除远程分支 5 删除文件5 1 删除本地文件5 2 删除远程文件 6 删除提交6
  • openwrt出现md5sum mismatch错误

    原文地址 xff1a http catinmay com openwrt E5 87 BA E7 8E B0md5sum mismatch E9 94 99 E8 AF AF 刚刚帮人搞路由器一运行安装命令就会出现此错误 xff0c 错误提
  • python——系统交互subprocess

    目录 一 os与commands模块 1 os system 函数实例 2 os popen 函数实例 3 commands getstatusoutput 函数实例 二 subprocess模块 1 subprocess模块中的常用函数
  • strcat 你真的懂吗?

    http blog chinaunix net uid 26914516 id 4215338 html 声明 xff1a 使用GCC编译 strcat xff08 连接两字符串 xff09 函数定义 xff1a char strcat c
  • HTTP超全详解

    HTTP协议简介 超文本传输协议 xff08 英文 xff1a HyperText Transfer Protocol xff0c 缩写 xff1a HTTP xff09 是一种用于分布式 协作式和超媒体信息系统的应用层协议 HTTP是一个
  • 【Linux】三次握手和四次挥手详解

    三次握手和四次挥手 TCP 协议提供的是 xff1a 面向连接 可靠的 字节流服务 使用 TCP 协议通信的双发必须先建立连接 xff0c 然后才能开始数据的读写 双方都必须为该连接分配必要的内核资源 xff0c 以管理连接的状态和连接上数
  • Sion 450行的c++ HttpClient

    Sion Sion是一个轻量级的c 43 43 http客户端 xff0c 仅单头文件450行 xff0c 自带std string的扩展Sion is a lightweight C 43 43 HTTP Client with only
  • bluerov软件调试教程(一 )

    bluerov是目前最流行的一款消费级ROV xff0c 其架构简单 xff0c 可操作性强 xff0c 比同类型的ROV体验感要高很多 xff0c 本系列教程将从bluerov的软件调试 xff0c 硬件调试 xff0c 装舱等三个方面去
  • 安装完成Ubuntu20.04之后要做的事:基础配置、界面美化、异常处理与常用软件的安装

    文章目录 一 换源1 1 通过软件更新1 2 通过修改源文件 二 安裝显卡驱动2 1 解决显卡驱动安装的错误 三 设置新建文件模板四 卸载系统软件五 安裝中文输入法5 1 安装5 2 解决键盘短暂失灵和延迟的问题 六 双系统时间同步七 修改
  • 【C++】Windows客户端与Ubuntu服务器基于socket的简易网络编程

    C 43 43 Windows客户端与Ubuntu服务器基于socket的简易网络编程 服务器端 本人使用的clion远程连接的ubuntu服务器来运行以下代码 xff0c 理论上也可以直接放在服务器上 创建项目后 xff0c 先运行以下代
  • Python中pyusb的开发及使用

    Python中pyusb的开发及使用 因为项目的需求 xff0c 需要将FPGA端的图像像素数据经过USB2 0协议传输到PC端 xff0c 因此需要使用python的pyusb库来进行数据的发送和接收 以下纪录在使用pyusb库的方法和所
  • NVIDIA Jetson Xavier NX 实现官方Jeston-inference深度学习样例

    一 jetson inference相关项目组件的下载 首先附上官方提供的jetson inference项目文件的Github仓库地址 xff0c 大家可以自行前往下载 jetson inference下载地址 xff1a https g
  • CMake 混编c和c++代码

    准备工作 wsl 或者 有linux 系统 购买阿里云或者其他云服务器 xff09 cmake gcc git 等一些必要的软件安装 环境 windows 下 的 wsl wsl 安装下载 例子 拿 Unix网络编程 举例 作者对原生接口进
  • Ros中使用find_object_2d快速实现物体的检测识别

    运行环境 xff1a Ubuntu16 04 ros kinetic版本 准备工作 xff1a 需要r提前安装的webcam的驱动 xff0c 这里推荐使用两种usb cam和uvc camera xff08 1 xff09 usb cam
  • ubuntu16.04多版本Python任意切换(亲测有效)

    UBUNTU16 04的系统安装ROS之后 xff0c 自带的是Python2 7 12的版本 然后实际使用中 xff0c 可能用到其他工具需要装Python3 5以上的版本 安装完之后 xff0c 可能经常在编译某些工程的时候出现一些代码

随机推荐

  • ROS中级教程学习笔记1-手动创建ROS package

    之前在基础教程中 xff0c 我们使用的是catkin create pkg自动创建ros包 xff0c 实际上就是一个package xml文件和CMakeLists txt文件加文件夹 xff0c 所以手动创建看看能不能呢和自动创建有一
  • 串口分类

    串口一般来说就是UART xff0c 它实际只定义了数据链路层的规范 xff0c 也就是起始位 数据位 停止位 但是在不同的物理层又分为 xff1a TTL串口 RS232串口 RS485串口等 TTL串口 xff1a 它是MCU芯片之间进
  • ROS通信机制(二) —— 服务(service)与srv文件

    文章目录 简述特点相关常用命令通信模型核心元素通信过程代码示例 xff08 服务端和客户端 xff09 服务端 xff08 server cpp xff09 客户端 xff08 client cpp xff09 配置 CMakeLists
  • 学习日志之stm32——固件库编程规范

    对stm32固件库驱动的一点理解 stm32f4固件库主要有三个抽象层 xff1a gt 用C语言定义的寄存器地址与所有bits xff0c bit fields和寄存器的映射 所有后面这些都可以寻址 gt 所有的片上外设可用功能的程序接口
  • vs2010 webapi开发http请求以及website中如何实现http请求

    一 vs2010 webapi开发 第一步 xff1a 创建 第二步 xff1a 离线安装NuGet 1 复制链接到浏览器打开 xff1a http visualstudiogallery msdn microsoft com 27077b
  • 字节和bit的大小端简介

    C语言的位域虽然很多人强烈建议不要使用 xff0c 但现有系统里还广泛存在位域的使用 xff0c 所以还是很有必要理清楚的 对big endian和little endian的区别 xff0c 很多人认为是对多字节数据类型而言 其实 xff
  • C++ 数字与char*的转换

    目录 1 数字转char 1 1 sprintf1 2 itoa1 3 ltoa ultoa 2 char 转数字2 1 atoi2 2 atol2 3 atof2 4 strtol2 5 strtoul2 6 strtod 1 数字转ch
  • 【C语言】printf输出16进制: %x %02x %#x

    x即按十六进制输出 xff0c 英文字母小写 xff0c 右对齐 02X有以下变化 xff1a 英文字母变大写 xff0c 如果输出字符不足两位的 xff0c 输出两位宽度 xff0c 右对齐 xff0c 空的一位补0 超过两位的 xff0
  • 【c语言】结构体初始化4中方法

    今天在6轴传感器的驱动代码源文件中看到结构体没见过的写法 xff1a typedef struct uint8 t xlda 1 uint8 t gda 1 uint8 t tda 1 uint8 t not used 01 5 lsm6d
  • 【debug】stm32 指针奇数地址问题导致HardFault

    很久很久没有记录过debug了 xff0c 今天有空就正好记录一下 嵌入式开发 xff0c stm32F407的MCU的开发板 遇到如下问题 xff1a 变量的地址竟然为奇数 xff01 xff01 xff01 导致程序运行到写入该地址的数
  • 【Autosar】学习总结-BSW层

    一 简介 AUTOSAR AUTomotive Open Systems ARchitecture xff0c 汽车开放系统架构 1 优势 xff1a 有利于提高软件复用度 xff0c 尤其是跨平台的复用度 xff1b 便于软件的交换与更新
  • 【PWM】从stm32到pwm到OLED屏幕调光到晚上不要玩手机

    一 前言 最近做项目 xff0c 配置了单片机中PWM波形输出 xff0c 配置单片机中的一个引脚输出PWM波 xff0c 示波器查看这个波形 xff0c 做了实践操作 xff0c 有一些感想 xff0c 将一些了解过的知识和常识结合 xf
  • 算法提高 高精度加法

    1051 算法提高 高精度加法 时间限制 1 Sec 内存限制 256 MB 提交 5 解决 2 提交 状态 讨论版 题目描述 在C C 43 43 语言中 xff0c 整型所能表示的范围一般为 231到231 xff08 大约21亿 xf
  • 【Autosar】学习总结-MCAL

    一 简介 MCAL xff1a 微控制器抽象层 xff1b 位于BSW层中的最下层 xff1b MCAL细分 xff0c 可将驱动分为 xff1a 微控制器驱动 存储器驱动 通信驱动 IO驱动 xff1a 二 MCAL的配置 xff08 E
  • 【2022】年度总结

    一 月报 xff1a 1 一月 二月 初入新公司 xff0c 还在试用期 xff1b 进的外包安卓手机升级项目 xff0c 是一个短期的项目 xff0c 3 4个月左右 xff1b 第一次了解到外包项目原来是这种模式 xff1a 建立黄区
  • 【笔试总结 网络】IP地址分类 划分子网 子网掩码 (相关例题分析)

    xff08 最近做了很多春招公司笔试卷子 xff0c 发现很多是学过的东西 xff0c 看着很熟悉 xff0c 就是不会 很多学过的概念模棱两可 xff0c 这在笔试中很吃亏 说不会吧会点 xff0c 说会吧 xff0c 做不出来 就比如关
  • 网页登录时密码如何传输?

    今天突发奇想想看下一般网站登录时密码是如何传输的 首先是QQMail xff0c gmail xff0c 各大网上银行等对于我非常重要的登录网站 xff1a https https的安全性自然是很高 其次是通常的腾讯微博以及其他腾讯常用的网
  • C/C++中简单数据结构的对齐

    这里只讨论简单的数据结构 xff0c 从MSDN上的例子开始 struct x char a 1 byte int b 4 bytes short c 2 bytes char d 1 byte 在没有对齐的情况下 xff0c x 中的所有
  • yolo数据增强以及批量修改图片和xml名

    记录下打完标签对数据集进行扩增 xff0c 数据增强后的图片及标签名字进行修改 xff0c 重点在代码只需更改文件名就可使用 无论数据增强还是修改名称 xff0c 标签框位置都会跟着改变 xff01 xff01 xff01 前人之鉴 xff
  • 利用select实现服务器和客户端的随时收发

    服务器代码实现 xff1a include lt stdio h gt include lt sys types h gt include lt sys socket h gt include lt arpa inet h gt inclu