linux 下UDP通信(附加测试代码)

本文提供了一段集成了客户端、服务端及广播消息服务端的UNIX网络编程代码示例,包括服务端代码、客户端代码及性能测试实例。代码通过多线程并发执行,实现高效的数据传输与处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自csdn博客:http://blog.youkuaiyun.com/rao_warrior/article/details/8188687

运行环境:centos 6.3  

说明 :UNIX 网络编程测试代码

将客户端、服务端、以及广播消息的服务端都集成一段代码里面,个人感觉还不错呵呵呵

里面的注释不多,但是应该不难读懂的,还算比较容易

可以把一面代码直接贴下来,用gcc  编译跑一下,会发现在效果还不错吐舌头

  1. #include <stdio.h>  
  2. #include <sys/types.h>          /* See NOTES */  
  3. #include <sys/socket.h>  
  4. #include <netinet/in.h>  
  5. #include <string.h>  
  6. #include <errno.h>  
  7. #include <stdlib.h>  
  8. #include <arpa/inet.h>  
  9. #include <unistd.h>  
  10.   
  11. typedef struct sockaddr_in sockaddr_in;  
  12. typedef struct sockaddr sockaddr;  
  13.   
  14. int main(int argc, char ** argv) {  
  15.   
  16.     sockaddr_in srv, cli;  
  17.     int fd, sfd, is_server;  
  18.   
  19.   
  20.     if (argc < 3) {  
  21.         printf(  
  22.                 "please put the arguments ,like ./a.out addr_ip  addr_port [server/client/broad]");  
  23.         return -1;  
  24.     }  
  25.     if (argc >= 4) {  
  26.         if (strcmp("server", argv[3]) == 0) {  
  27.             is_server = 1;  
  28.             printf("i am server \n");  
  29.         } else if (strcmp("client", argv[3]) == 0) {  
  30.             is_server = 0;  
  31.             printf("i am client \n");  
  32.         } else if(strcmp("broad",argv[3]) == 0){  
  33.             is_server = 2;  
  34.             printf("i want broad msg ,broad ip:X.X.X.255 \n");  
  35.         } else {  
  36.             printf("arguments error\n");  
  37.             return -1;  
  38.         }  
  39.     } else {//default  
  40.         is_server = -1 ;  
  41.         printf("i could recv and send msg  ,muti process\n");  
  42.     }  
  43.     memset(&srv, 0, sizeof(srv));  
  44.     srv.sin_port = htons(atoi(argv[2]));  
  45.     srv.sin_family = AF_INET;  
  46.   
  47.     if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {  
  48.         perror("server socket error");  
  49.     }  
  50.     if(is_server != -1){  
  51.         fd = 1-is_server ;  
  52.     }else{  
  53.         fd = fork();  
  54.         if (fd < 0) {  
  55.             perror("fork error");  
  56.             return -1;  
  57.         }  
  58.     }  
  59.   
  60.     if (0 == fd) { //service is_server == 1  
  61.         char recvbuf[1024];  
  62.         char ip[50];  
  63.         socklen_t len;  
  64.         int rnu = 0;  
  65.         srv.sin_addr.s_addr = INADDR_ANY ;  
  66.         int bfd;  
  67.         if ((bfd = bind(sfd, (sockaddr*) &srv, sizeof(sockaddr))) < 0) {  
  68.             perror("bind error");  
  69.         }  
  70.         while (1) {  
  71.             memset(recvbuf, 0, sizeof(recvbuf));  
  72.             len = sizeof(sockaddr);  
  73.             if((rnu = recvfrom(sfd, recvbuf, sizeof(recvbuf), 0, (sockaddr*) &cli,&len))<0) {  
  74.                 printf("recvfrom error");  
  75.             } else {  
  76.                 printf("from:%s,recv:%s",inet_ntop(AF_INET, &cli.sin_addr, ip, sizeof(ip)), recvbuf);  
  77.                 if (is_server!=-1 && sendto(sfd, recvbuf, strlen(recvbuf), 0, (sockaddr*) &srv, len) < 0) {  
  78.                     perror("sendto error");  
  79.                 }  
  80.                 //printf("send:%s\n",   inet_ntop(AF_INET, &srv.sin_addr, ip, sizeof(ip)));  
  81.                 sleep(2);  
  82.             }  
  83.         }  
  84.   
  85.         close(sfd);  
  86.   
  87.     }else if(-1 == fd){//broadcast  
  88.         char recvbuf[1024];  
  89.         char ip[50];  
  90.         socklen_t len;  
  91.         int rnu = 0;  
  92.   
  93.         srv.sin_addr.s_addr = INADDR_ANY ;  
  94.         int bfd;  
  95.         if ((bfd = bind(sfd, (sockaddr*) &srv, sizeof(sockaddr))) < 0) {  
  96.             perror("bind error");  
  97.         }  
  98.         while (1) {  
  99.             memset(recvbuf, 0, sizeof(recvbuf));  
  100.             len = sizeof(sockaddr);  
  101.             int on_broadcast = 1;  
  102.             int rs = setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &on_broadcast,  
  103.                     sizeof(on_broadcast));  
  104.             if ((rs = inet_pton(AF_INET, "10.33.28.255", &srv.sin_addr)) <= 0) {  
  105.                 perror("inet_pton error:");  
  106.             }  
  107.             strcpy(recvbuf, "this is broad\n");  
  108.             if (sendto(sfd, recvbuf, strlen(recvbuf), 0, (sockaddr*) &srv, len)  
  109.                     < 0) {  
  110.                 perror("sendto error");  
  111.             }  
  112.             printf("send:%s\n",  
  113.                     inet_ntop(AF_INET, &srv.sin_addr, ip, sizeof(ip)));  
  114.             sleep(2);  
  115.         }  
  116.   
  117.         close(sfd);  
  118.     }else {  
  119.         char sendbuf[1024], *p = sendbuf;  
  120.         ssize_t bs;  
  121.         char ip[50];  
  122.         socklen_t len = sizeof(sockaddr);  
  123.         inet_aton(argv[1], &srv.sin_addr);  
  124.         while (1) {  
  125.             memset(sendbuf, 0, sizeof(sendbuf));  
  126.             bs = sizeof(sendbuf);  
  127.             bs = getline(&p, &bs, stdin);  
  128.             bs = sendto(sfd, sendbuf, bs, 0, (sockaddr*) &srv, len);  
  129.             printf("sendto:%s", sendbuf);  
  130.             if(is_server!=-1 && (bs = recvfrom(sfd, sendbuf, sizeof(sendbuf), 0, (sockaddr*) &cli,&len))>0){  
  131.                 printf("from:%s,recv:%s",inet_ntop(AF_INET, &cli.sin_addr, ip, sizeof(ip)),sendbuf);  
  132.             }  
  133.         }  
  134.         close(sfd);  
  135.     }  
  136.   
  137. }  

下面是一个很不错的select的例子,避免了调用fork而产生的新进程的开销:

下面是server 代码:

  1. #include <stdio.h>  
  2.  #include <stdlib.h>  
  3.   
  4. #include <sys/types.h>          /* See NOTES */  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <string.h>  
  8. #include <errno.h>  
  9. #include <unistd.h>  
  10. #include <arpa/inet.h>  
  11. #define MAXLINE  1024  
  12. typedef struct sockaddr_in sockaddr_in ;  
  13. typedef struct sockaddr sockaddr ;  
  14. #define MAX_FD_CONN     1000  
  15.   
  16. int main(int argc ,char ** argv){  
  17.   
  18.     int sock ,con;  
  19.     int nready ,nfd;  
  20.     sockaddr_in srv,cli ;  
  21.   
  22.     if((sock=socket(AF_INET ,SOCK_STREAM,0))==-1){  
  23.         perror("socket ");  
  24.         return -1 ;  
  25.     }  
  26.   
  27.     bzero(&srv,0);  
  28.     srv.sin_family = AF_INET ;  
  29.     srv.sin_port = htons(8070);  
  30.     srv.sin_addr.s_addr = htonl (INADDR_ANY) ;  
  31.   
  32.     if((bind(sock,(sockaddr*)&srv,sizeof(sockaddr)))< 0){  
  33.         perror("bind");  
  34.         return -1 ;  
  35.     }  
  36.     listen(sock,10);  
  37.     char buf[1024];  
  38.     fd_set rset,allfd ;  
  39.     int conns[ MAX_FD_CONN ] ,i ,nr;  
  40.     socklen_t len ;  
  41.     for(i =0 ;i<MAX_FD_CONN;i++)  
  42.         conns[i] = -1;  
  43.   
  44.     FD_ZERO(&allfd);  
  45.     FD_SET(sock,&allfd );  
  46.     nfd = sock+1;  
  47. <span style="white-space:pre">  </span>FD_SET(sock,&allfd);  
  48.     while(1){  
  49.         rset=allfd; //这个是相当的关键一行哦,UNP(1)上说,select 对参数是有修改的,一定要注意保存啊,不然会出现意想不到的问题  
  50.   
  51.         nready = select(nfd, &rset,NULL,NULL,NULL );  
  52.         if (FD_ISSET(sock,&rset)) {  
  53.             len = sizeof(sockaddr);  
  54.             if ((con = accept(sock, (sockaddr*) &cli, &len)) == -1) {  
  55.                 perror("accept");  
  56.                 continue;  
  57.             }  
  58.             for(i =0 ;i<MAX_FD_CONN;i++){ /*if maxsize >MAX_FD_CONN, throw and close the connect */  
  59.                 if(conns[i ] == -1){  
  60.                     conns[i] = con;  
  61.                     FD_SET(con,&allfd);  
  62.                     break;  
  63.                 }  
  64.             }  
  65.             if(MAX_FD_CONN == i)  
  66.                 close(con);  
  67.             if(nfd <= con)  
  68.                 nfd = con +1;  
  69.   
  70.             if(--nready <= 0){  
  71.                 continue ;  
  72.             }  
  73.         }  
  74.   
  75.   
  76.         for(i =0 ;i<MAX_FD_CONN;i++){  
  77.             if(conns[i]== -1)  
  78.                 continue ;  
  79.             if(FD_ISSET(conns[i], &rset)){  
  80.                 bzero(buf,sizeof(buf));  
  81.                 if((nr=read(conns[i],buf,sizeof(buf)))<=0){  
  82.                     close(conns[i]);  
  83.                     FD_CLR(conns[i],&allfd);  
  84.                     continue ;  
  85.                 }else{  
  86.                     printf("read:%s\n",buf);  
  87.                     write(conns[i],buf, nr);  
  88.                 }  
  89.             }  
  90.             if(--nready <= 0)  
  91.                 break;  
  92.         }  
  93.     }  
  94.     close(sock);  
  95.   
  96.     return 0;  
  97. }  

在此我也把客户端连接的测试的代码也贴出来,分享一下,也防止以后忘了呵呵呵

  1. #include <stdio.h>  
  2.  #include <stdlib.h>  
  3.   
  4. #include <sys/types.h>          /* See NOTES */  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <string.h>  
  8. #include <errno.h>  
  9. #include <unistd.h>  
  10. #include <arpa/inet.h>  
  11. #define MAXLINE  1024  
  12. typedef struct sockaddr_in sockaddr_in ;  
  13. typedef struct sockaddr sockaddr ;  
  14.   
  15.   
  16. int main(int argc ,char ** argv){  
  17.   
  18.     int sock ;  
  19.     int sel ,nfd;  
  20.     sockaddr_in srv,cli ;  
  21.   
  22.     if((sock=socket(AF_INET ,SOCK_STREAM,0))==-1){  
  23.         perror("socket ");  
  24.         return -1 ;  
  25.     }  
  26.   
  27.     bzero(&srv,0);  
  28.     srv.sin_family = AF_INET ;  
  29.     srv.sin_port = htons(atoi(argv[2]));  
  30.     inet_pton(AF_INET,argv[1],&srv.sin_addr);  
  31.   
  32.     char buf[1024];  
  33.     fd_set rset ,wset;  
  34.     FD_ZERO(&rset);  
  35.     FD_ZERO(&wset);  
  36.     FD_SET(STDIN_FILENO ,&rset );  
  37.     FD_SET(sock ,&rset );  
  38.     if(connect(sock,(sockaddr*)&srv, sizeof(sockaddr))<0){  
  39.         perror("connect:");  
  40.         return -1 ;  
  41.     }  
  42.     perror("con");  
  43.       
  44.     nfd = sock+1;  
  45.     int rn ;  
  46.     bzero(buf,sizeof(buf));  
  47.     while((sel = select(nfd, &rset,&wset,NULL,NULL ))){  
  48.         printf("select begin\n");  
  49.   
  50.         if(FD_ISSET(sock,&rset)){  
  51.             bzero(buf,sizeof(buf));  
  52.             read(sock,buf,sizeof(buf));  
  53.             printf("read:%s\n",buf);  
  54.         }  
  55.         if(FD_ISSET(STDIN_FILENO,&rset)){  
  56.             bzero(buf,sizeof(buf));  
  57.             rn = read(STDIN_FILENO, buf,sizeof(buf));  
  58.             if(rn>0)  
  59.                 FD_SET(sock,&wset );  
  60.         }  
  61.         if(FD_ISSET(sock, &wset)){  
  62.             int wn = write(sock,buf,rn );  
  63.             bzero(buf,sizeof(buf));  
  64.             FD_CLR(sock,&wset );  
  65.         }  
  66.   
  67.   
  68.         FD_SET(STDIN_FILENO ,&rset );  
  69.         FD_SET(sock ,&rset );  
  70.     }  
  71.     close(sock);  
  72.   
  73.   
  74.     return 0;  
  75. }  
  1. 下面给出一个性能测试实例  
  1.   
  1. 下面使用200个线程,而且是并发执行哦!每个线程写入1000*1000*10B的数据  
  1. 测试成功  
  1. <pre name="code" class="cpp">typedef struct sockaddr_in      sockaddr_in;  
  2. typedef struct sockaddr         sockaddr ;  
  3.   
  4. void *thread_fun(void*arg ){  
  5.       
  6.         struct sockaddr_in ser,cli ;  
  7.         int fd ,bs,fdc,i;  
  8.         socklen_t len;  
  9.         char buf[1024];  
  10.   
  11.         bzero(&ser,sizeof(sockaddr));  
  12.         ser.sin_port = 8080;  
  13.         inet_pton(AF_INET,"10.33.28.230",(void*)&ser.sin_addr);  
  14.         ser.sin_family = AF_INET ;  
  15.         fd = socket(AF_INET,SOCK_STREAM, 0);   
  16.         if(fd<0)  
  17.                 perror("socket error\n");  
  18.         //int nZero=0;  
  19.         //setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));  
  20.         printf("threadID:%d\n",(int)arg);  
  21.         sleep(2);  
  22.         connect(fd,(sockaddr*)&ser,sizeof(sockaddr));  
  23.         for(i=0;i<1000*1000;i++){  
  24.                 bzero(buf,sizeof(buf));  
  25.                 sprintf(buf,"%10d",(int)arg);  
  26.                 if(write(fd,buf,strlen(buf))<=0)  
  27.                         perror("write error:");  
  28.         }     
  29. //      printf("%d\n",i);  
  30.         close(fd);  
  31. //      sleep(1);  
  32.         pthread_exit((void*)arg);  
  33. }  
  34. const int num_thre = 200;  
  35. int main(){  
  36.         int i =0;  
  37.         int res;  
  38.        pthread_t send_msg[num_thre];  
  39.         for(i=0;i<num_thre;i++){  
  40.                 if(pthread_create(send_msg+i,NULL,thread_fun,i)!=0)  
  41.                         printf("pthread create error\n");  
  42.         }  
  43.   
  44.         for(i=0;i<num_thre;i++){  
  45.                 pthread_join(send_msg[i],(void**)(&res));  
  46.                 printf("%dover\n",res);  
  47.         }  
  48.         printf("over \n");  
  49.         return 0;  
  50. }  
  51. </pre><br>  
  52. <br>  
  53. <pre></pre>  
  54. <p></p>  
  55. <pre></pre>  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值