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

select 同时接收普通数据 和 带外数据

这是一个服务器程序,使用select同时接收普通数据(监视可读) 和 带外数据(监视异常)。

#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<stdlib.h>

int main(int argc, char* argv[])
{
	if (argc <= 2)
	{
		return 1;
	}
	const char* ip = argv[1];
	int port = atoi(argv[2]);

	struct sockaddr_in address;
	bzero(&address, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_port = htons(port);
	inet_pton(AF_INET, ip, &address.sin_addr);

	int listenfd = socket(PF_INET, SOCK_STREAM, 0);
	assert(listenfd >= 0);

	int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
	assert(ret != -1);

	ret = listen(listenfd, 5);
	assert(ret != -1);

	struct sockaddr_in client_address;
	socklen_t client_addrlength = sizeof(client_address);
	int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
	if (connfd < 0)
	{
		printf("errno is: %d\n", errno);
		close(listenfd);
	}

	char buf[1024];
	fd_set read_fds;	/* 一个用于测试 可读状态的 文件描述符集合 */
	fd_set exception_fds;	/* 一个用于测试 异常状态的 文件描述符集合 */
	FD_ZERO(&read_fds);
	FD_ZERO(&exception_fds);

	while (1)
	{
		memset(buf, '\0', sizeof(buf));
		/* 每次调用 select 前都要重新在 read_fds 和 exception_fds 中设置文件描述符 connfd,因为事件发生之后文件描述符集合将被内核修改 */
		FD_SET(connfd, &read_fds);
		FD_SET(connfd, &exception_fds);
		ret = select(connfd + 1, &read_fds, NULL, &exception_fds, NULL);
		if (ret < 0)
		{
			printf("selection failure\n");
			break;
		}

		/* 对于可读事件,采用普通的 recv 函数读取数据 */
		if (FD_ISSET(connfd, &read_fds))
		{
			ret = recv(connfd, buf, sizeof(buf) - 1, 0);
			if (ret <= 0)
			{
				break;
			}
			printf("get %d bytes of normal data: %s\n", ret, buf);
		}
		/* 对于异常事件,采用带 MSG_OOB 标志的 recv 函数读取带外数据 */
		else if (FD_ISSET(connfd, &exception_fds))
		{
			ret = recv(connfd, buf, sizeof(buf) - 1, MSG_OOB);
			if (ret <= 0)
			{
				break;
			}
			printf("get %d bytes of oob data:  %s\n", ret, buf);
		}
	}
	close(connfd);
	close(listenfd);
	return 0;
}

相关文章:

  • I/O复用的高级应用之一:非阻塞 connect———使用 select 实现(也可以用 poll 实现)
  • I/O复用的高级应用:同时处理 TCP 和 UDP 服务
  • I/O复用的高级应用:聊天室程序———实例代码
  • select、poll、epoll的使用方法 和 使用场景
  • 使用统一事件源的方式同时处理信号和 I/O
  • 使用SIGURG信号接受带外数据
  • 信号 ——《Linux高性能服务器编程》第10章——读书笔记
  • Linux 文件I/O 及其 多个相关函数
  • python——学校课程预习+复习
  • Linux 进程———详解
  • Linux服务器实例程序———使用定时器列表处理非活动连接
  • 各种最短路问题的常用算法模板
  • Linux高级进程编程———在任意两个进程间传递文件描述符:使用 sendmsg 和 recvmsg 实现
  • Linux 线程———详解
  • Linux 中与字符串相关的函数strpbrk、strcasecmp、strspn(不间断更新)
  • Akka系列(七):Actor持久化之Akka persistence
  • Cookie 在前端中的实践
  • EOS是什么
  • Git 使用集
  • Hibernate最全面试题
  • Java Agent 学习笔记
  • JavaScript 奇技淫巧
  • nginx 配置多 域名 + 多 https
  • Python语法速览与机器学习开发环境搭建
  • spring boot下thymeleaf全局静态变量配置
  • springboot_database项目介绍
  • Vue UI框架库开发介绍
  • 大整数乘法-表格法
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 分布式任务队列Celery
  • 后端_ThinkPHP5
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 跨域
  • 前端面试总结(at, md)
  • 深入浅出Node.js
  • 异步
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 阿里云重庆大学大数据训练营落地分享
  • 从如何停掉 Promise 链说起
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #define与typedef区别
  • (k8s中)docker netty OOM问题记录
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (强烈推荐)移动端音视频从零到上手(上)
  • (五)MySQL的备份及恢复
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • .gitignore文件_Git:.gitignore
  • .htaccess 强制https 单独排除某个目录
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .net core 依赖注入的基本用发