Linux 下的 UDP 编程
2019-10-14
关键字:C 语言的 UDP 编程与实例
UDP 连接是一种无连接的网络连接协议。
Linux 下的 UDP 编程的函数接口与 TCP 差不了多远。在 UDP 通信模型中,也是以 C/S 模型来通信的。
服务端的函数调用流程主要有以下几个:
1、socket()
2、bind()
3、recvfrom() / sendto()
4、close()
客户端的函数调用流程主要有以下几个:
1、socket()
2、sendto() / recvfrom()
3、close()
socket()、bind() 函数:
略,有需要的可以参阅 TCP 编程的文章。
sendto() 函数:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
这个函数与 TCP 编程里的 send() 很像,只不过多了两个参数 dest_addr 与 addrlen 而已。由于 UDP 是无连接式的网络通信,因此很容易猜到这多出来的两个参数和数据接收方的地址有关。
参数 dest_addr 就是一个在填写时要用 sockaddr_in 结构体类型,使用时强转成 sockaddr 结构体类型的参数。用于填写数据接收方的 IP 地址、端口号与通信模式信息。
参数 addrlen 就是结构体 dest_addr 的长度。
recvfrom() 函数:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
这个函数与上面 sendto() 几乎一样。
参数 src_addr 与 addrlen 用于保存数据发送方的网络地址信息。
实例
客户端:
int main(int argc, char *argv[]) { int fd = -1; int port = 17173; struct sockadr_in sin; // 1. 创建 socket fd if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(-1); } bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); // host to net,本地字节序转换成网络字节序。 if(inet_pton(AF_INET, "192.168.77.3", (void *)&sin.sin_addr) != 1) { perror("inet_pton"); exit(-1); } char buf[64]; while(1) { bzero(buf, 64); if(fgets(buf, 64 - 1, stdin) == NULL) { perror("fgets"); continue; } sendto(fd, buf, strlen(buf), 0, (struct socketaddr *)&sin, sizeof(sin)); //退出判断。 } close(fd); return 0; }
服务端:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> int main() { int fd = -1; struct sockaddr_in sin; if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(-1); } //允许绑定地址与端口的快速重用。 int b_reuse = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int)); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); exit(-1); } char buf[64]; struct sockaddr_in cin; socklen_t addrlen = sizeof(cin); while(1) { bzero(buf, 64); if(recvfrom(fd, buf, 64 - 1, 0, (struct sockaddr *)&cin, &addrlen) < 0) { perror("recvfrom"); continue; } char ipv4[16]; if(!inet_ntop(AF_INET, (void *)&cin.sin_addr, ipv4, sizeof(cin))) { perror("inet_ntop"); exit(-1); } printf("received from(%s:%d), data:%s\n", ipv4, ntohs(sin.sin_port), buf); } return 0; }