Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2112671
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-06-18 15:32:58

一.
1. 流程描述
udp的demo既有server端又有client端,两者互相通信
client --> sendto    --> recvfrom
server--> recvfrom --> sendto

2. 代码
2.1 client.c
  1. cong@msi:/work/test/tcpip/14udp/client$ cat client.c
  2. #include "utils.h"

  3. //#define TIME_SERV_ADDR "192.168.4.98"
  4. #define TIME_SERV_ADDR "127.0.0.1"

  5. void dg_cli(FILE* fp, int sockfd, const struct sockaddr* pservaddr, socklen_t servlen)
  6. {
  7.     int n;
  8.     char sendline[MAXLINE], recvline[MAXLINE];
  9.     while(fgets(sendline, MAXLINE, fp) != NULL)
  10.     {
  11.         //write(sockfd, sendline, strlen(sendline));
  12.         //这儿的pservaddr一定要初始化,要不client就不知道要发给谁了
  13.         sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); //a.sendto发送到服务器
  14.         //这儿的第5个参数设为NULL,因为client不需要知道是谁发给它的,所以书上说这儿有个bug
  15.         n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);            //d.recvfrom接收服务器的数据
  16.         recvline[n] = 0;
  17.         fputs(recvline, stdout);
  18.     }
  19. }

  20. int main ( int argc, char *argv[] )
  21. {
  22.     int sockfd, n;
  23.     struct sockaddr_in servaddr;
  24.     char recvline[1024];
  25.     //sockfd = socket(AF_INET, SOCK_STREAM, 0);
  26.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  27.     if(sockfd < 0)
  28.         return -1;
  29.     bzero(&servaddr, sizeof(servaddr));
  30.     servaddr.sin_family = AF_INET;
  31.     servaddr.sin_port = htons(13999);
  32.     inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);

  33.     //connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  34.     dbmsg("next dg_cli");
  35.     dg_cli(stdin, sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  36.     return EXIT_SUCCESS;
  37. }
2.2 serv.c
  1. cong@msi:/work/test/tcpip/14udp/serv$ cat udpserv.c
  2. #include "utils.h"

  3. void dg_echo(int sockfd, struct sockaddr* pcliaddr, socklen_t clilen)
  4. {
  5.     int n;
  6.     socklen_t len;
  7.     char mesg[MAXLINE];
  8.     while(1)
  9.     {
  10.         len = clilen;
  11.         //recvfrom把client的端口号与地址保存在pcliaddr中
  12.         n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);  //b.recvfrom收到client的数据
  13.         //因为recvfrom己保存了client的端口与地址,所以serv就知道该发到哪儿去了,这就是pcliaddr的作用
  14.         sendto(sockfd, mesg, n, 0, pcliaddr, len);               //c.sendto发送到client
  15.     }
  16. }

  17. int main ( int argc, char *argv[] )
  18. {
  19.     int sockfd, connfd;
  20.     struct sockaddr_in servaddr, cliaddr;
  21.     pid_t childpid;
  22.     char buf[1024];
  23.     int len;
  24.     //sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  25.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);    //由SOCK_STREAM改为SOCK_DGRAM
  26.     if(sockfd < 0)
  27.         return -1;
  28.     bzero(&servaddr, sizeof(servaddr));
  29.     servaddr.sin_family = AF_INET;
  30.     servaddr.sin_port = htons(13999);
  31.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  32.     //inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  33.      
  34.     bind(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr)); //bind就行了没有listen
  35.     dg_echo(sockfd, (struct sockaddr*)&cliaddr, sizeof(cliaddr));

  36.     return EXIT_SUCCESS;
  37. }
这儿打印了pcliaddr

  1. 在内核的include/linux/socket.h中
  2. struct sockaddr {
  3.     sa_family_t sa_family; /* address family, AF_xxx */
  4.     char sa_data[14]; /* 14 bytes of protocol address */
  5. };

  6. 所以打印如下:
  7. for(i=0; i<14; i++)
  8.     dbmsg("%d= 0x%x",i, (unsigned char)pcliaddr->sa_data[i]);

  9. udpserv.c:dg_echo[16]: 0= 0xb5
  10. udpserv.c:dg_echo[16]: 1= 0xba
  11. udpserv.c:dg_echo[16]: 2= 0x7f
  12. udpserv.c:dg_echo[16]: 3= 0x0
  13. udpserv.c:dg_echo[16]: 4= 0x0
  14. udpserv.c:dg_echo[16]: 5= 0x1
  15. udpserv.c:dg_echo[16]: 6= 0x0
  16. udpserv.c:dg_echo[16]: 7= 0x0
  17. udpserv.c:dg_echo[16]: 8= 0x0
  18. udpserv.c:dg_echo[16]: 9= 0x0
  19. udpserv.c:dg_echo[16]: 10= 0x0
  20. udpserv.c:dg_echo[16]: 11= 0x0
  21. udpserv.c:dg_echo[16]: 12= 0x0
  22. udpserv.c:dg_echo[16]: 13= 0x0
  23. 其中 0xb5 0xba = b5ba=46522 --> client的端口号
  24.      7f 00 00 01--> 127.0.0.1 --> client的地址

2.3
client.rar (下载后改名为client.tar.gz)
serv.rar (下载后改名为serv.tar.gz)
二. 修改版
1. clinet.c
  1. cong@msi:/work/test/tcpip/16udp/client$ cat udpclient.c
  2. #include "utils.h"
  3. #include <unistd.h>
  4. #include <sys/time.h>
  5. #include <stdlib.h>

  6. //#define TIME_SERV_ADDR "192.168.4.98"
  7. #define TIME_SERV_ADDR "127.0.0.1"

  8. long int get_now_us_time()
  9. {
  10.     struct timeval start;
  11.     long int now_time;
  12.     gettimeofday(&start, NULL);
  13.     now_time = start.tv_sec*1000+ start.tv_usec/1000;
  14.     return now_time;
  15. }


  16. void dg_cli(FILE* fp, int sockfd, const struct sockaddr* pservaddr, socklen_t servlen)
  17. {
  18.     int n, i,j;
  19.     long int t1,t2;
  20.     char sendline[MAXLINE], recvline[MAXLINE];
  21.     //while(fgets(sendline, MAXLINE, fp) != NULL)
  22.     //while(1)
  23.     for(j=0; j<3; j++)
  24.     {
  25.         memset(sendline, 0, sizeof(sendline));
  26.         for(i=0; i<64; i++)
  27.         {
  28.             sendline[i] = i;
  29.         }
  30.         t1 = get_now_us_time();
  31.         //write(sockfd, sendline, strlen(sendline));
  32.         sendto(sockfd, sendline, 64, 0, pservaddr, servlen);

  33.         n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
  34.         t2 = get_now_us_time();
  35.         printf("time=%ld\n", t2-t1);
  36.         recvline[n] = 0;
  37.         fputs(recvline, stdout);
  38.         sleep(1);
  39.     }

  40. }

  41. int main ( int argc, char *argv[] )
  42. {
  43.     int sockfd, n;
  44.     struct sockaddr_in servaddr;
  45.     char recvline[1024];
  46.     //sockfd = socket(AF_INET, SOCK_STREAM, 0);
  47.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  48.     if(sockfd < 0)
  49.         return -1;
  50.     bzero(&servaddr, sizeof(servaddr));
  51.     servaddr.sin_family = AF_INET;
  52.     servaddr.sin_port = htons(9000);
  53.     inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);

  54.     //connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  55.     dbmsg("next dg_cli");
  56.     dg_cli(stdin, sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  57.     return EXIT_SUCCESS;
  58. }
2.server
  1. cong@msi:/work/test/tcpip/16udp/serv$ cat udpserv.c
  2. #include "utils.h"

  3. char * sock_ntop(const struct sockaddr *sa, socklen_t salen)
  4. {
  5.     char portstr[8];
  6.     static char str[128]; /* Unix domain is largest */
  7.     struct sockaddr_in *sin = (struct sockaddr_in *) sa;
  8.     //only process AF_INET
  9.     if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
  10.         return(NULL);
  11.     if (ntohs(sin->sin_port) != 0) {
  12.         snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));
  13.         strcat(str, portstr);
  14.     }
  15.     return(str);
  16. }

  17. void dg_echo(int sockfd, struct sockaddr* pcliaddr, socklen_t clilen)
  18. {
  19.     int n;
  20.     int i;
  21.     socklen_t len;
  22.     char mesg[MAXLINE];
  23.     while(1)
  24.     {
  25.         len = clilen;
  26.     #if 0
  27.         for(i=0; i<14; i++)
  28.             dbmsg("%d= 0x%x",i, (unsigned char)pcliaddr->sa_data[i]);
  29.     #endif
  30.         n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
  31.         dbmsg("n=%d, len=%d", n, len);
  32.         for(i=0; i<n; i++)
  33.             printf("%d=0x%x ",i, mesg[i]);
  34.         printf("\n");
  35.         sendto(sockfd, mesg, n, 0, pcliaddr, len);
  36.     }
  37. }

  38. int main ( int argc, char *argv[] )
  39. {
  40.     int sockfd, connfd;
  41.     struct sockaddr_in servaddr, cliaddr;
  42.     pid_t childpid;
  43.     char buf[1024];
  44.     int len;
  45.     //sockfd = socket(AF_INET, SOCK_STREAM, 0);
  46.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  47.     if(sockfd < 0)
  48.         return -1;
  49.     bzero(&servaddr, sizeof(servaddr));
  50.     servaddr.sin_family = AF_INET;
  51.     servaddr.sin_port = htons(9000);
  52.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  53.     //inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  54.      
  55.     bind(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));
  56.     dg_echo(sockfd, (struct sockaddr*)&cliaddr, sizeof(cliaddr));

  57.     return EXIT_SUCCESS;
  58. }
2.3
client.rar(下载后改名为client.tar.gz)
serv.rar(下载后改名为serv.tar.gz)

阅读(1186) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~