UDP (User Datagram Protocol):用户数据报协议。
UDP 是一个不可靠的通信协议,没有重传和确认,没有有序控制,也没有拥塞控制。可以简单地理解为,在 IP 报文的基础上,UDP 增加的能力有限。
UDP编程UDP中客户端和服务器端交互的图解:

UDP Server :
- Create UDP socket.
- Bind the socket to server address.
- Wait until datagram packet arrives from client.
- Process the datagram packet and send a reply to client.
- Go back to Step 3.
UDP Client :
- Create UDP socket.
- Send message to server.
- Wait until response from server is received.
- Process reply and go back to step 2, if necessary.
- Close socket descriptor and exit.
主要是使用以下函数:
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,
struct sockaddr *from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,
const struct sockaddr *to, socklen_t *addrlen);
recvfrom的参数含义:
-
sockfd :本地创建的套接字描述符
-
buff :指向本地缓存的指针
-
nbytes :最大接收数据字节
-
flags :与 I/O 相关的参数
-
from 和 addrlen:返回对端发送方的地址和端口等信息
返回值:实际接收的字节数。
sendto的参数意义:
-
sockfd :本地创建的套接字描述符
-
buff :指向本地缓存的指针
-
nbytes :最大接收数据字节
-
flags :与 I/O 相关的参数
-
to 和 addrlen,表示发送的对端地址和端口等信息。
UDP Server:
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char sendbuffer[MAXLINE];
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int n;
socklen_t len = (socklen_t)sizeof(cliaddr); //len is value/resuslt
for (;;) {
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
sprintf(sendbuffer, "have recieve %d bytes", strlen(buffer));
sendto(sockfd, (const char *)sendbuffer, strlen(sendbuffer), 0,
(const struct sockaddr *) &cliaddr, len);
fprintf(stdout, "%s\n", sendbuffer);
}
return 0;
}
UDP Client:
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
socklen_t len = (socklen_t)sizeof(servaddr); //len is value/resuslt
// send msg
while (fgets(buffer, MAXLINE, stdin) != NULL) {
int i = strlen(buffer);
if (buffer[i - 1] == '\n') {
buffer[i - 1] = 0;
}
sendto(sockfd, (const char *)buffer, strlen(buffer), 0,
(const struct sockaddr *) &servaddr, len);
fprintf(stdout, "message: %s have sent.\n", buffer);
int n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL,
(struct sockaddr *) &servaddr, &len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
}
close(sockfd);
return 0;
}
情况1: 只运行客户端、不开启服务端
可以看见,没有响应,也发送不了数据。程序会一直阻塞在 recvfrom 上。
情况2: 先开启服务端,再开启客户端

也可以使用多个UDP客户端去和UDP服务器端通信,不再细述。
总结- UDP 是无连接的数据报程序,和 TCP 不同,不需要三次握手建立一条连接。
- UDP 程序通过 recvfrom 和 sendto 函数直接收发数据报报文。
[1] 极客时间 · 网络编程实战 :06 | 嗨,别忘了UDP这个小兄弟