2022-3-1

select

在这里插入图片描述
select、poll、epoll都是实现io多路复用的手段
select函数有5个参数
int nfds:表示管理的数量,例如下图中就应该为8
在这里插入图片描述
fd_set *readfds:表示应当监听的会发生读操作的文件的文件描述符集合,例如c1用户发送连接请求,这时lfd就会收到c1发来的请求,于是lfd,也就是文件3就会发生读操作

fd_set *writefds:表示应当监听的会发生写操作的文件的文件描述符集合

fd_set *exceptfds:表示应当监听的会发生异常的文件的文件描述符集合

上述三个文件描述符集合,传入的时候是我们想要监听的文件描述符,传出的时候是发生了对应事件的文件描述符,例如上图,读操作的文件描述符,传入的时候在3、5、6上都是1,其他都是0,select执行完后,就只有5、6是1了,因为3没有发生读操作

struct timeval *timeout:表示监听的持续时间

返回值代表了所有监听集合中发生的事件的综述,上图就是3

文件描述符集合就是上图右下角那种类似数组的东西,里面存的0或1

select的相关函数

在这里插入图片描述
这些函数是对文件描述符集合进行操作的

使用上图监听读操作的3、5、6,写操作的4、6,异常的7进行解释

void FD_ZERO(fd_set *set):清空一个文件描述符集合

fd_set rset;
FD_ZERO(&rset);

void FD_SET(int fd, fd_set *set):将待监听的文件描述符,添加到集合中

FD_SET(3, &rset);
FD_SET(5, &rset);
FD_SET(6, &rset);

void FD_CLR(int fd, fd_set *set):将一个文件描述符从监听集合中移除
例如用户c1结束了与服务器的连接

FD_CLR(4, &rset);

int FD_ISSET(int fd, fd_set *set):判断一个文件描述符是否在监听集合中
返回值:在的话是1,不在是0

网络字节序转换

由于历史遗留问题,我们计算机端的字节序是按小端法存储的,也即高位存高地址,低位存低地址,而网络中(IP协议)是按大端法存储的,与小端法刚好相反,于是就有用于字节序转换的函数
在这里插入图片描述
在这里插入图片描述
但是由于我们一般使用的是点存十进制的IP地址,例如192.168.1.1,他本质是一个string,而函数要一个uint32,很麻烦,所以一般使用一个封装好的函数
在这里插入图片描述
INADDR_ANY表示获取本机上任意一个能使用的ip

在这里插入图片描述
af:当前使用的IP协议----AF_INET(ipv4)、AF_INET6(ipv6)
src:点存十进制的ip地址
dst:转换后的网络字节序
return 1代表转换成功,0代表失败

实现

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<ctype.h>

int main(int argc, char *argv[]){
	int i,n,j;
	int listenfd,connfd;

	char buf[BUFSIZ];

	struct sockaddr_in clie_addr, serv_addr;
	socklen_t clie_addr_len;

	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	int opt=1;
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	bzero(&serv_addr,sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(9527);
	bind(listenfd,(struct sockaddr *)&serv_addr, sizeof(serv_addr));
	listen(listenfd,128);

	fd_set rset,allset;
	FD_ZERO(& allset);
	FD_SET(listenfd, &allset);
	
	int ret,maxfd=listenfd;
	while(1){
		rset=allset;
		ret = select(maxfd+1, &rset, NULL, NULL, NULL, 10);
		if(FD_ISSET(listenfd, &rset){
			clie_addr_len = sizeof(clie_addr);
			connfd = accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len);
			FD_SET(connfd, &allset);
			if(maxfd<connfd)
				maxfd=connfd;
			if(ret==1)
				continue;
		}
		for(i=listenfd+1; i<=maxfd; ++i){
			if(FD_ISSET(i, &rset){
				n= read(i,buf,sizeof(buf));
				if(n==0){
					close(i);
					FD_CLR(i,&allset);
				}
				for(j=0; j<n; ++j){
					buf[j]=toupper(buf[j]);
				}
				write(i, buf, n);
			}
		}
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值