Linux下Select用法

本文介绍了一个使用UDP协议实现的客户端与服务器通信的代理程序,包括客户端向服务器发送数据并接收回应的流程,以及服务器端如何响应客户端请求。通过使用socket编程,展示了如何在不同端口间进行高效的数据交换。

 由于时间关系,先将我用的代码写到这里,稍后解释。这里服务器端有两个可能阻塞的描述符:一个是网络的,另一个是来自终端的,用select可以保证无论是客户端还是终端给它发送数据,它都可以处理,当然还有更高效率的实现方式,就是poll和epoll,网上有它们查找过程的不同。这里不赘述。

18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <stdio.h>
22 #define SERVER_PORT 6000
23 
24 void UdpRequest(int sockfd,const struct sockaddr_in *add, int len)
25 {
26     int n;
27     char buf[1024] = "Good good study! Up";
28     char recvBuf[1024];
29     while (fgets(buf,1024,stdin)!= NULL) {
30          /*向服务器发送数据*/
31         sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)add,len);
32         memset(recvBuf,0,1024);
33          /*接收回应*/
34         n = recvfrom(sockfd,recvBuf,1024,0,NULL,NULL);
35         recvBuf[n] = '\0';
36         fputs(recvBuf,stdout);
37         memset(buf,0,1024);
38     }
39 }
40 
41 int main(int argc, const char *argv[])
42 {
43     int sockfd;
44     struct sockaddr_in addr;
45     if (argc != 2) {
46         fprintf(stderr,"usage:client ipaddr port\n");
47         exit(1);
48     }
49 
50      /*创建一个udp 数据报类型套接字     */
51     sockfd = socket(AF_INET,SOCK_DGRAM,0);
52     if (sockfd < 0) {
53         fprintf(stderr,"Socket error\n");
54         exit(1);
55     }
56     bzero(&addr,sizeof(addr));
57 
58     addr.sin_family = AF_INET;
59     addr.sin_port = htons(SERVER_PORT);
60 
61     if (inet_aton(argv[1],&addr.sin_addr) < 0) {
62         fprintf(stderr,"Inet_aton error");
63         exit(1);
64     }
65     UdpRequest(sockfd,&addr,sizeof(addr));
66     close(sockfd);
67     return 0;
68 }

下面是服务器端:

16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <netinet/in.h>
21 #include <sys/socket.h>
22 #define SOCKET_PORT 6000
23  /*作用是回复客户端请求*/
24  void Response(int sockfd)
25  {
26      char msg[1024];
27     struct sockaddr_in clientAddr;
28     int addrlen = sizeof(clientAddr);
29     int actualNum;
30     actualNum = recvfrom(sockfd,msg,1024,0,(struct sockAddr*)&clientAddr,&addrlen);
31     sendto(sockfd,msg,actualNum,0,(struct sockAddr*)&clientAddr,addrlen);
32  }
33 
34 int main(void)
35 {
36     fd_set rfds;
37     struct timeval tv;
38     int retval;
39     char buf[256];
40     int sockfd;
41      /*创建socket*/
42     struct sockaddr_in addr;
43     sockfd = socket(AF_INET,SOCK_DGRAM,0);
44     if (sockfd < 0) {
45         fprintf(stderr,"Socket error");
46         exit(1);
47     }
48 
49     bzero(&addr,sizeof(addr));
50 
51     addr.sin_family = AF_INET;
52     addr.sin_port = htons(SOCKET_PORT);
53     addr.sin_addr.s_addr= htonl(INADDR_ANY);
54      /*为服务器绑定一个端口 */
55         if (bind(sockfd,(struct sockAddr*)&addr,sizeof(addr)) < 0) {
56         fprintf(stderr,"Bind error");
57         exit(1);
58     }
59 
60     memset((void*)buf,0,sizeof(char)*256);
61     
62     FD_ZERO(&rfds);
63     FD_SET(0, &rfds);
64     FD_SET(sockfd,&rfds);
65  
66     tv.tv_sec = 5;
67     tv.tv_usec = 0;
69     while(1)
70     {
71 
72         retval = select(sockfd + 1, &rfds, NULL, NULL, &tv);
73         if (retval == -1)
74             perror("select()");
75         else if (retval)
76         {
77                 if (FD_ISSET(0,&rfds)) 
78             {
79             printf("Data is available now.\n");
80             scanf("%s",buf);
81             printf("You input a:%s\n",buf);
82             memset((void*)buf,0,sizeof(char)*256);
83             }
84                 else if(FD_ISSET(sockfd,&rfds))
85                 {
86                     Response(sockfd);
87                 }
88         }
89         FD_ZERO(&rfds);
90         FD_SET(0,&rfds);
91         FD_SET(sockfd,&rfds);
92 
94     }
95     close(sockfd);
96     return 0;
97 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值