Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5204001
  • 博文数量: 553
  • 博客积分: 13864
  • 博客等级: 上将
  • 技术积分: 11041
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-28 21:25
个人简介

个人Blog: hhktony.com

文章分类

全部博文(553)

文章存档

2015年(1)

2014年(2)

2013年(12)

2012年(384)

2011年(154)

分类: LINUX

2011-11-29 02:39:25

我们前面已经学习网络程序的一个很大的部分,由这个部分的知识,我们实际上可以写出大部分的基于TCP协议的网络程序了.
现在在 Linux下的大部分程序都是用我们上面所学的知识来写的.我们可以去找一些源程序来参考一下.这一章,我们简单的学习一下基于UDP协议的网络程序. 

5.1 两个常用的函数
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr * from int *fromlen)
int sendto(int sockfd,const void *msg,int len,unsigned int flags,struct sockaddr *to int tolen)

sockfd,buf,len的意义和read,write一样,分别表示套接字描述符,发送或接收的缓冲区及大小.

recvfrom负责从 sockfd接收数据,如果from不是NULL,那么在from里面存储了信息来源的情况,如果对信息的来源不感兴趣,可以将from和fromlen 设置为NULL.

sendto负责向to发送信息.此时在to里面存储了收信息方的详细资料.

5.2 一个实例

运行UDP Server程序

执行./server &

点击(此处)折叠或打开

  1. /* 服务端程序 server.c */
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <unistd.h>

  7. #include <netdb.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <sys/types.h>
  11. #include <arpa/inet.h>

  12. #define SERVER_PORT 8000
  13. #define MAX_MSG_SIZE 1024

  14. void udps_respon(int sockfd)
  15. {
  16.     struct sockaddr_in addr;
  17.     int n;
  18.     socklen_t addrlen;
  19.     char msg[MAX_MSG_SIZE];

  20.     while (1) {            /* 从网络上读 和 写到网络上面去 */
  21.     memset(msg, 0, sizeof(msg));
  22.     addrlen = sizeof(struct sockaddr);
  23.     /*
  24.      *ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
  25.      * struct sockaddr *src_addr, socklen_t * addrlen);
  26.      */
  27.     n = recvfrom(sockfd, msg, MAX_MSG_SIZE, 0,
  28.          (struct sockaddr *) &addr, &addrlen);
  29.     /* 显示服务端已经收到了信息 */
  30.     fprintf(stdout, "I have received %s", msg);

  31.     /*echo back*/
  32.     /*
  33.      *ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
  34.      * const struct sockaddr *dest_addr, socklen_t addrlen);
  35.      */
  36.     sendto(sockfd, msg, n, 0, (struct sockaddr *) &addr, addrlen);
  37.     }
  38. }

  39. int main(int argc, char *argv[])
  40. {
  41.     int sockfd;
  42.     struct sockaddr_in addr;
  43. #if 0
  44.     struct sockaddr_in {
  45.     sa_family_t sin_family;
  46.     in_port_t sin_port;
  47.     struct in_addr sin_addr;
  48.     unsigned char sin_zero[8];
  49.     };
  50. #endif

  51.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  52.     fprintf(stderr, "Socket Error:%s\n", strerror(errno));
  53.     exit(1);
  54.     }
  55. #ifdef _DEBUG_
  56.     fprintf(stdout, "Create a new UDP socket, socket = %d\n", sockfd);
  57. #endif

  58.     bzero(&addr, sizeof(struct sockaddr_in));
  59.     addr.sin_family = AF_INET;    /*ipv4 */
  60.     addr.sin_addr.s_addr = htonl(INADDR_ANY);
  61.     addr.sin_port = htons(SERVER_PORT);

  62.     if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))
  63.     < 0) {
  64.     fprintf(stderr, "Bind Error:%s\n", strerror(errno));
  65.     exit(1);
  66.     }
  67. #ifdef _DEBUG_
  68.     fprintf(stdout, "Bound successfully.\n");
  69. #endif

  70.     udps_respon(sockfd);
  71.     close(sockfd);

  72.     return 0;
  73. }

点击(此处)折叠或打开

  1. /* 客户端程序 */
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <unistd.h>

  7. #include <netdb.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <sys/types.h>
  11. #include <arpa/inet.h>

  12. #define MAX_BUF_SIZE 1024

  13. void udpc_requ(int sockfd, const struct sockaddr_in *addr, socklen_t len)
  14. {
  15.     char buffer[MAX_BUF_SIZE];
  16.     int n;
  17.     while (fgets(buffer, MAX_BUF_SIZE, stdin)) {    /* 从键盘读入,写到服务端 */
  18.     sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *) addr,
  19.      len);
  20.     bzero(buffer, MAX_BUF_SIZE);

  21.     memset(buffer, 0, sizeof(buffer));

  22.     /* 从网络上读,写到屏幕上 */
  23.     n = recvfrom(sockfd, buffer, MAX_BUF_SIZE, 0, NULL, NULL);
  24.     if (n <= 0) {
  25.      fprintf(stderr, "Recv Error %s\n", strerror(errno));
  26.      return;
  27.     }
  28.     buffer[n] = 0;
  29.     fprintf(stderr, "get %s", buffer);
  30.     }
  31. }


  32. int main(int argc, char *argv[])
  33. {
  34.     int sockfd;
  35.     unsigned short port;
  36.     struct sockaddr_in addr;
  37. #if 0
  38.     struct sockaddr_in {
  39.     sa_family_t sin_family;
  40.     in_port_t sin_port;
  41.     struct in_addr sin_addr;
  42.     unsigned char sin_zero[8];
  43.     };
  44. #endif

  45.     if (argc != 3) {
  46.         fprintf(stderr, "Usage:%s \n", argv[0]);
  47.         exit(1);
  48.     }

  49.     port = (unsigned short) strtol(argv[2], NULL, 10);

  50.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))
  51.     < 0) {
  52.         fprintf(stderr, "Create socket failed: %s\n", strerror(errno));
  53.         exit(1);
  54.     }
  55. #ifdef _DEBUG_
  56.     fprintf(stdout, "Create a new UDP socket, socket = %d\n", sockfd);
  57. #endif

  58.     /* 填充服务端的资料 */
  59.     bzero(&addr, sizeof(struct sockaddr_in));
  60.     addr.sin_family = AF_INET;
  61.     addr.sin_port = htons(port);
  62.     /*int inet_pton(int af, const char *src, void *dst); */
  63.     inet_pton(AF_INET, argv[1], &addr.sin_addr);

  64.     /*
  65.      *int connect(int sockfd, const struct sockaddr *addr,
  66.      * socklen_t addrlen);
  67.      */
  68.     if (connect
  69.     (sockfd, (struct sockaddr *) &addr,
  70.      sizeof(struct sockaddr_in)) == -1) {
  71.         fprintf(stderr, "connect error %s\n", strerror(errno));
  72.         exit(1);
  73.     }

  74.     udpc_requ(sockfd, &addr, sizeof(struct sockaddr_in));
  75.     close(sockfd);

  76.     return 0;
  77. }
命令来启动服务程序。我们可以使用netstat -ntupl命令来观察服务程序绑定的IP地址和端口
可以看到udp处有“0.0.0.0:8000”的内容,说明服务程序已经正常运行,可以接收主机上任何IP地址且端口为8000的数据。

3、运行UDP Client程序

执行./client 127.0.0.1 8000

命令来启动客户程序,使用127.0.0.1来连接服务程序,执行效果如下:

Hello, World!
Hello, World!
this is a test
this is a test
^D
输入的数据都正确从服务程序返回了,按ctrl+d可以结束输入,退出程序。
阅读(1435) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~