20240118(IO多路复用)作业

本文档展示了如何使用C语言中的select和poll函数分别在TCP客户端和服务器端实现并发处理,包括创建套接字、绑定、监听、接收和发送消息等操作。
摘要由CSDN通过智能技术生成
1> 使用select实现TCP客户端的并发
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/select.h>


int main(int argc, const char *argv[])
{
	//create socket
	int csktfd=socket(AF_INET,SOCK_STREAM,0);
	if(csktfd==-1){
		perror("socket error");
		return -1;
	}
	//form address structure
	struct sockaddr_in csin;
	csin.sin_family=AF_INET;
	csin.sin_port=htons(12345);
	csin.sin_addr.s_addr=inet_addr("192.168.122.150");
	//bind
	if(bind(csktfd,(struct sockaddr *)&csin,sizeof(csin))==-1){
		perror("bind error");
		return -1;
	}
	//connect
	struct sockaddr_in ssin;
	ssin.sin_family=AF_INET;
	ssin.sin_port=htons(7890);
	ssin.sin_addr.s_addr=inet_addr("192.168.122.150");
	if(connect(csktfd,(struct sockaddr *)&ssin,sizeof(ssin))==-1){
		perror("connect error");
		return -1;
	}

	//select
	fd_set fds,tmpfds;
	FD_SET(0,&fds);
	FD_SET(csktfd,&fds);
	tmpfds=fds;
	char buf[128]="";
	while(1){
		int slct=select(csktfd+1,&tmpfds,NULL,NULL,NULL); 
		if(FD_ISSET(0,&tmpfds)){
			scanf("%s",buf);
			
			send(csktfd,buf,sizeof(buf),0);
			if(strcmp(buf,"quit")==0) break;
		}
		if(FD_ISSET(csktfd,&tmpfds)){
			bzero(buf,sizeof(buf));
			recv(csktfd,buf,sizeof(buf),0);
			printf("receive message from server:%s\n",buf);
		}

		tmpfds=fds;
	}
	//close socket
	close(csktfd);
	return 0;
}
2> 使用poll实现TCP服务器的并发
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/select.h>
#include <poll.h>


int main(int argc, const char *argv[])
{
	//create socket
	int ssktfd=socket(AF_INET,SOCK_STREAM,0);
	if(ssktfd==-1){
		perror("socket error");
		return -1;
	}

	//set socket option to reuse imidiately
	int reuse = 1;
    if(setsockopt(ssktfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
    {
        perror("setsockopt error");
        return -1;
    }
    printf("set socket reusable successfully\n");
	//form address structure
	struct sockaddr_in ssin;
	ssin.sin_family=AF_INET;
	ssin.sin_port=htons(7890);
	ssin.sin_addr.s_addr=inet_addr("192.168.122.150");
	//bind
	if(bind(ssktfd,(struct sockaddr *)&ssin,sizeof(ssin))==-1){
		perror("bind error");
		return -1;
	}
	
	//listen
	if(listen(ssktfd,128)==-1){
		perror("listen error");
		return -1;
	}
	
	//poll
	struct pollfd pfd[1024];
	int pfdlen=sizeof(pfd)/sizeof(struct pollfd);
	pfd[0].fd=0;
	pfd[0].events=POLLIN;
	pfd[1].fd=ssktfd;
	pfd[1].events=POLLOUT;
	struct sockaddr_in sktbuf[1024];

	while(1){
		printf("wait event......\n");
		int res=poll(pfd,pfdlen,-1);
		if(res==-1){
			perror("poll error");
			return -1;
		}else if(res==0){
			printf("timeout\n");
			return -1;
		}

		for(int cli=0;cli<pfdlen;cli++){
			//fd==0 get message from terminal
			char buf[128]="";
			if(pfd[cli].fd==0 && pfd[cli].events==POLLIN){
				scanf("%s",buf);
				printf("server get message from terminal: %s\n",buf);
				//send message to all clients

			}

			//fd=3 create new server communication socket
			if(pfd[cli].fd==3 && pfd[cli].events==POLLIN){
				//create new server socket
				struct sockaddr_in nsin;
				socklen_t len=sizeof(nsin);
				int nsfd=accept(ssktfd,(struct sockaddr *)&nsin,&len);
				if(nsfd==-1){
					perror("accept error");
					return -1;
				}
				printf("create a new connection with the fd=%d\n",nsfd);

				pfd[cli].fd=nsfd;
				pfd[cli].events=POLLIN;
				//restore client address
				sktbuf[nsfd]=nsin;

			}
			
			//fd>3 send and recieve message
			if(pfd[cli].fd>3 && pfd[cli].events==POLLOUT){
				char buf[128]="";
				//recieve message
				//bzero(buf,sizeof(buf));
				int res=recv(cli,buf,sizeof(buf),0);
				//disconnection
				if(res=0){
					close(cli);
					//FD_CLR(cli,&fds);
					//update maxfd
					continue;
				}

				printf("message from[%s:%d]%d:%s\n",inet_ntoa(sktbuf[cli].sin_addr),sktbuf[cli].sin_port,cli,buf);
				//send message back
				strcat(buf,"--**--");
				send(cli,buf,sizeof(buf),0);
			}

		}
	}

	//close socket
	close(ssktfd);
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值