【Linux Socket 编程入门】06 - 拉个骡子溜溜:UDP编程模型代码分析
2017-01-20 04:16
429 查看
(一) 前情
在第4篇里面,介绍了TCP编程实例,现在,我们再看看UDP编程实例。才完美嘛。(二)上个菜:一个UDP程序分析
开胃:UDP客户服务器编程模型
与TCP面向连接,可靠的编程模型不同,UDP面向数据报,是不可靠的编程模型。因此它的编程模型相较于TCP,会简单一些。上菜:UDP编程实例分析
服务器端程序:(可以参照上面的编程模型,理解下面这段代码)#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h> #define MYPORT "4950" //端口号 #define MAXBUFLEN 100 //buffer的最大长度 //get sockaddr, IPv4 or IPv6 void *get_in_addr(struct sockaddr *sa) { if(sa->sa_family == AF_INET) { return &(((struct sockaddr_in *)sa)->sin_addr); } return &(((struct sockaddr_in6 *)sa)->sin6_addr); } int main(void) { int sockfd; struct addrinfo hints, *servinfo, *p; struct sockaddr_storage their_addr; socklen_t addr_len; char s[INET6_ADDRSTRLEN]; char buf[MAXBUFLEN]; int rv; int numbytes; memset(&hints, 0, sizeof(hints)); //一定先清0整个结构体。 hints.ai_family = AF_UNSPEC; //自动选择IPv4或者IPv6 hints.ai_socktype = SOCK_DGRAM; //采用UDP编程模型 hints.ai_flags = AI_PASSIVE; // 填充本机IP if(0 != (rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo))) { //填充addrinfo结构体。 fprintf(stderr, "getaddrinfo:%s\n", gai_strerror(rv)); return 1; } //for循环,选择第一个可用的IP地址。 for(p = servinfo; p != NULL; p = p->ai_next) { if(-1 == (sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol))) { perror("listener: socket"); continue; } if(-1 == (bind(sockfd, p->ai_addr, p->ai_addrlen))) { close(sockfd); //绑定失败,一定要close(),释放已经分配的网络描述符。 perror("listener: bind"); continue; } break; } if(NULL == p) { fprintf(stderr, "listener: failed to bind\n"); return 2; } freeaddrinfo(servinfo); // 后面不会再使用servinfo,可以释放掉。 printf("listener: waiting to recvfrom...\n"); addr_len = sizeof(their_addr); if(-1 == (numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0, (struct sockaddr *)&their_addr, &addr_len))) {//绑定成功后,直接recvfrom(),等待数据。 perror("recvfrom"); exit(1); } printf("listener: got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof(s))); printf("listener: packet is %d bytes long\n", numbytes); buf[numbytes] = '\0'; printf("listener: packet contains \"%s\"\n", buf);//打印接收到的数据。 close(sockfd); return 0; }
客户端程序:(可以参照上面的编程模型,理解下面这段代码)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h> #define SERVERPORT "4950" //定义端口号,必须与服务器端相等。 int main(int argc, char *argv[]) { int sockfd; struct addrinfo hints, *servinfo, *p; int rv; int numbytes; if(argc != 3) { fprintf(stderr, "usage: talker hostname message\n"); exit(1); } memset(&hints, 0, sizeof(hints)); //首先,清0结构体。 hints.ai_family = AF_UNSPEC; //自动选择IPv4,IPv6. hints.ai_socktype = SOCK_DGRAM; //采用UDP protocol. if(0 != (rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo))) { //填充addrinfo结构体 fprintf(stderr, "getaddrinfo:%s\n", gai_strerror(rv)); return 1; } ////for循环,选择第一个可用的IP地址。 for(p = servinfo; p != NULL; p = p->ai_next) { if(-1 == (sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol))) { perror("talker: socket"); continue; } break; } if(NULL == p) { fprintf(stderr, "talker: failed to create socket\n"); return 2; } if(-1 == (numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, p->ai_addr, p->ai_addrlen))) { // 啥也不用做,直接sendto()发送数据 perror("talker: sendto"); exit(1); } freeaddrinfo(servinfo); printf("talker: send %d bytes to %s\n", numbytes, argv[1]); close(sockfd); return 0; }
测试步骤:
测试的环境为:ubuntu 16.04
利用gcc分别编译客户端程序和服务器端程序。编译完成后,先启动服务器端程序(假设在当前目录下),在shell下执行:
./server然后再启动客户端程序:打开另一个终端,在shell中执行(利用loop back IP address进行测试):
./client 127.0.0.1 "Hello, World!"
测试结果:
在服务器端会看到如下信息:
listener: waiting to recvfrom... listener: got packet from 127.0.0.1 listener: packet is 12 bytes long listener: packet contains "Hello World!"
在客户端会看到如下信息:
talker: send 12 bytes to 127.0.0.1
--THE END--
相关文章推荐
- Linux/Unix服务端和客户端Socket编程入门实例代码
- Linux socket编程入门及客户端服务器端通信实现 – 提高篇:TCP连接过程分析
- 【Linux Socket 编程入门】02 - OSI七层模型与DoD四层模型
- linux-socket tcp客户端服务器编程模型及代码详解
- linux socket编程客户端模型(用getaddrinfo)
- Linux网络编程socket错误分析
- 轻松搞定iPhone socket 编程 用代码说话(iphone开发入门 4)
- Linux网络编程socket错误分析
- TCP--UDP常用代码(socket编程--网上搜索自己整理的)
- Linux网络编程socket错误分析
- 基于linux 的socket UDP编程例程
- 续实例解析SOCKET编程模型之异步通信篇(上) 代码
- linux socket编程 udp connect例子
- Linux下C语言编程入门-17关于服务器模型
- socket编程(udp tcp)代码备忘 C++/C
- Linux网络编程socket错误分析
- Linux环境下的Socket编程(入门)
- Linux C socket 编程之UDP
- 基于visual c++之windows核心编程代码分析(33)实现防火墙模型
- linux socket编程服务端模型(用getaddrinfo)