原文:https://github.com/angrave/SystemProgramming/wiki/Networking%2C-Part-6%3A-Creating-a-UDP-server
有多种函数调用可用于发送 UDP 套接字。我们将使用较新的 getaddrinfo 来帮助设置套接字结构。
请记住,UDP 是一种简单的基于数据包('data-gram')协议;两个主机之间没有建立连接。
首先,初始化提示 addrinfo 结构以请求 IPv6 被动数据报套接字。
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6; // INET for IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
接下来,使用 getaddrinfo 指定端口号(我们不需要指定主机,因为我们正在创建服务器套接字,而不是将数据包发送到远程主机)。
getaddrinfo(NULL, "300", &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);
端口号<1024,因此程序将需要root
权限。我们也可以指定服务名称而不是数字端口值。
到目前为止,调用类似于 TCP 服务器。对于基于流的服务,我们将调用listen
并接受。对于我们的 UDP 服务,我们可以开始等待数据包到达套接字 -
struct sockaddr_storage addr;
int addrlen = sizeof(addr);
// ssize_t recvfrom(int socket, void* buffer, size_t buflen, int flags, struct sockaddr *addr, socklen_t * address_len);
byte_count = recvfrom(sockfd, buf, sizeof(buf), 0, &addr, &addrlen);
addr 结构将保存有关到达数据包的发送方(源)信息。注意sockaddr_storage
类型足够大,可以容纳所有可能类型的套接字地址(例如 IPv4,IPv6 和其他套接字类型)。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
int s;
struct addrinfo hints, *result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6; // INET for IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "300", &hints, &res);
int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (bind(sockfd, res->ai_addr, res->ai_addrlen) != 0) {
perror("bind()");
exit(1);
}
struct sockaddr_storage addr;
int addrlen = sizeof(addr);
while(1){
char buffer[1000];
ssize_t byte_count = recvfrom(sockfd, buf, sizeof(buf), 0, &addr, &addrlen);
buffer[byte_count] = '\0';
}
printf("Read %d chars\n", len);
printf("===\n");
printf("%s\n", buffer);
return 0;
}