【Linux学习笔记55】TCP服务器IO模型之非阻塞轮询

引言

之前都介绍了多线程,多进程的方式解决各种TCP服务器的问题。那么本篇笔记主要记录单进程非阻塞的方式处理TCP服务器的服务。使用的方法就是轮询的机制处理,虽然这种方法很少使用,因为其占用的CPU资源很多,但是还是很有必要了解一下。

各种模型的理解图

在这里插入图片描述

代码实现

server.c:

#include "head4sock.h"
#include "kernel_list.h"

typedef struct
{
	int fd ;
	struct list_head list;
}client;

client *new_cli(int fd)
{
	client *new = malloc(sizeof(client));
	if (new != NULL)
	{
		new->fd =fd ;
		INIT_LIST_HEAD(&new->list);
	}
	return new;
}

client *init_list(void)
{
	client *head = malloc(sizeof(client));
	if (head != NULL)
	{
		INIT_LIST_HEAD(&head ->list);
	}
	return head;
}

int main(int argc, char const *argv[])
{
	if(argc != 2)
	{
		printf("Usage: %s <PORT>\n", argv[0]);
		exit(0);
	}

	// 创建一个TCP套接字
	int fd = Socket(AF_INET, SOCK_STREAM, 0); //设为IPv4的套接字

	// 绑定地址(IP:PORT)
	struct sockaddr_in srvaddr, cliaddr;
	socklen_t len = sizeof(srvaddr);
	bzero(&srvaddr, len);

	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons(atoi(argv[1]));
	// inet_pton(AF_INET, "192.168.1.166", &srvaddr.sin_addr);
	srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	Bind(fd, (struct sockaddr *)&srvaddr, len);

	// 设置监听套接字
	Listen(fd, 3); //如果同时有人发出请求,能够同时处理若干个,在Linux中至少同时允许4+3个连接请求

	long val =fcntl(fd,F_GETFL); //得到当前的IO状态
	val |= O_NONBLOCK;
	fcntl(fd,F_SETFL,val); //设置fd为非阻塞状态

	client * head =init_list();
	int connfd;
	while (1)
	{
		 connfd = accept(fd, (struct sockaddr *)&cliaddr, &len);

		 if (connfd > 0)
		 {
			long val =fcntl(connfd,F_GETFL); //得到当前的IO状态
		 	val |= O_NONBLOCK;
		 	fcntl(connfd,F_SETFL,val); //设置connfd为非阻塞状态

			char peeraddr[50];
 			bzero(peeraddr, 50);
 			printf("new connection: %s:%hu\n",  //打印端口号
 						inet_ntop(AF_INET, &cliaddr.sin_addr, peeraddr, 50),
 						ntohs(cliaddr.sin_port));

			client * new = new_cli(connfd); //为了更好利用资源,使用动态链表将套接字起来
			list_add_tail(&new->list,&head->list); //将新的节点添加到链表中
		 }

	char buf[SIZE];
	struct list_head *pos,*n;
	list_for_each_safe(pos,n,&head->list)
	{
		client *tmp = list_entry(pos,client,list);
		bzero(buf,SIZE);
		int nread;
		if((nread=read(tmp->fd,buf,SIZE))==0)
		{
			list_del(pos);
			free(tmp);
		}
		else if(nread >0)  //此时有数据
		{
			printf("%s",buf );
		}
	}
}
}

client .c :

与上一篇一样

代码运行结果:

在这里插入图片描述
从图中可以看到 server占用的CPU资源比较多,效率比较低,非阻塞模型的轮询机制一般不采用。

发布了91 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/RayCongLiang/article/details/100996861