【Linux篇】IO多路复用

该代码示例展示了如何使用select模型创建一个TCP服务器,处理来自多个客户端的连接请求。服务器监听指定端口,接收客户端连接,为每个新连接创建子进程进行处理。客户端使用select进行输入输出的同步,可以读取服务器响应并发送数据。当接收到特定退出命令时,双方均会终止连接。
摘要由CSDN通过智能技术生成

 

 

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>
#include <sys/wait.h>
//select服务端
#define SERV_RESP_STR "SERVER:"
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define BACKLOG 5
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.163.128"

void child_data_handle(int signum)
{
	if(SIGCHLD == signum)
	{
		waitpid(-1,NULL,WNOHANG);
	}
}
void* client_data_handle(void *arg);
int main()
{
	int fd = -1;
	signal(SIGCHLD,child_data_handle);

	struct sockaddr_in sin;
	//1.socket
	fd = socket(AF_INET,SOCK_STREAM,0);
	if(fd < 0)
	{
		perror("socket");
		exit(1);
	}

	bzero(&sin,sizeof(sin));

	sin.sin_family = AF_INET;
	sin.sin_port = htons(SERV_IP);
	sin.sin_addr.s_addr = INADDR_ANY;
	//2.bind
	if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
	{
		perror("bind");
		exit(1);
	}
	//3.listen
	if(listen(fd,BACKLOG) < 0)
	{
		perror("listen");
		exit(1);
	}
	pid_t pid;
	int newfd = -1;
	struct sockaddr_in cin;
	socklen_t addrlen = sizeof(cin);
	while(1)
	{
		newfd = accept(fd,(struct sockaddr *)&cin,&addrlen);
		if(newfd < 0)
		{
			perror("accept");
			break;
		}
		pid = fork();
		if(pid < 0)
		{
			perror("fork");
			break;
		}
		if(pid == 0)
		{
			char ipv4_addr[16];
			if(!inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin)))
			{
				perror("inet_ntop");
				exit(1);
			}
			printf("client:(%s,%d)is connect!\n",ipv4_addr,ntohs(cin.sin_port));

			client_data_handle(&newfd);
			close(fd);
		}
		if(pid > 0)
		{
			close(newfd);
		}
	}

	close(fd);
}

void* client_data_handle(void *arg)
{
	int newfd = *(int *)arg;
	char buf[BUFSIZE];
	int ret = -1;
	printf("handle thread:newfd = %d\n",newfd);
	char resp_buf[BUFSIZE];
	while(1)
	{
		do
		{
			ret = read(newfd,buf,BUFSIZE-1);
		}while(ret < 0);
		if(ret <0 )
		{
			perror("read");
			exit(1);
		}
		if(!ret)
		{
			break;
		}
		printf("receive data:%s\n",buf);
		
		bzero(resp_buf,BUFSIZE);
		strncpy(resp_buf,SERV_RESP_STR,strlen(SERV_RESP_STR));
		strcat(resp_buf,buf);
		do
		{
			ret = write(newfd,resp_buf,strlen(resp_buf));
		}while(ret < 0);




		if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
		{
			printf("Client is exiting!\n");
			break;
		}

	}
	close(newfd);
	return NULL;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
//select客户端
#define SERV_RESP_STR "SERVER:"
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define SERV_PORT 5001
#define SERV_IP_ADDR "192.168.163.128"

int main(int argc,char **argv)
{
	int fd = -1;
	if(argc != 3)
	{
		exit(1);
	}
	int port = -1;
	port = atoi(argv[2]);

	struct sockaddr_in sin;

	fd = socket(AF_INET,SOCK_STREAM,0);
	if(fd < 0)
	{
		perror("socket");
		exit(1);
	}

	bzero(&sin,sizeof(sin));

	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	sin.sin_addr.s_addr = inet_addr(argv[1]);

	if(connect(fd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
	{
		perror("connect");
		exit(1);
	}

	fd_set rset;
	int maxfd = -1;
	struct timeval tout;
	char buf[BUFSIZE];
	int ret = -1;
	while(1)
	{
		FD_ZERO(&rset);
		FD_SET(0,&rset);
		FD_SET(fd,&rset);

		maxfd = fd;
		tout.tv_sec = 5;
		tout.tv_usec = 0;

		select(maxfd+1,&rset,NULL,NULL,&tout);

		if(FD_ISSET(0,&rset))//stdin have data
		{
			bzero(buf,BUFSIZE);
			do
			{
				ret = read(0,buf,BUFSIZE-1);
			}while(ret < 0);

			if(ret < 0)
			{
				perror("read");
				continue;
			}
			if(!ret) continue;//no data

			if(write(fd,buf,strlen(buf)) < 0)
			{
				perror("write");
				continue;
			}

			if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
			{
				printf("client is exited!\n");
				break;
			}

		}
		if(FD_ISSET(fd,&rset))//server have data
		{
			bzero(buf,BUFSIZE);
			do
			{
				ret = read(fd,buf,BUFSIZE-1);
			}while(ret < 0);
			if(ret < 0)
			{
				perror("read");
				continue;
			}
			if(!ret) break;
			printf("server said:%s\n",buf);
			if((strlen(buf) > strlen(SERV_RESP_STR))  &&   !strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
			{
				printf("client is exited!\n");
				break;
			}
		}

	}

	return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿gao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值