由于时间关系,先将我用的代码写到这里,稍后解释。这里服务器端有两个可能阻塞的描述符:一个是网络的,另一个是来自终端的,用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 }

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

被折叠的 条评论
为什么被折叠?



