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例子
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 函數直接收發數據報報文。
reference
[1] 極客時間 · 網絡編程實戰 :06 | 嗨,別忘了UDP這個小兄弟