首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

Beej's Guide 第 15 章:sendto() 與 recvfrom() —— 無連接數據報編程

     編輯:關於C

背景

數據報套接字 (SOCK_DGRAM, UDP) **無連接**。發送前無需 connect(),但每次發送必須指定**目標地址**;接收時可獲取**來源地址**。

sendto():發送數據報


#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *msg, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
  • sockfd:socket(AF_INET, SOCK_DGRAM, 0) 創建的描述符。
  • msg:發送數據緩衝區。
  • len:數據長度。
  • flags:通常 0 (可用 MSG_DONTROUTE 等)。
  • dest_addr:目標地址結構 (sockaddr_in 包含 IP+Port)。
  • addrlen:sizeof(struct sockaddr_in)。

返回:實際發送位元組數 (UDP 通常全發或全不發,異常返回 -1)。

recvfrom():接收數據報


ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
  • src_addr:輸出參數,發送方地址。
  • addrlen:輸入輸出,調用前設緩衝區大小,返回實際地址結構大小。

返回:接收位元組數,-1 表錯誤。

關鍵特性

  1. 無連接狀態:內核不維持連接上下文,每個包獨立路由。
  2. 邊界保持:sendto 一次發送 = recvfrom 一次接收 (不超過緩衝區)。不會像 TCP 產生黏包/分包。
  3. 不可靠:丟包、亂序、重複無保證。應用層需自行實現 ACK/重傳/序號 (如需可靠性)。
  4. 可選 connect():對 UDP connect() 僅綁定默認目標地址,允許用 send/recv 替代 sendto/recvfrom,並啟用內核端口不可達錯誤過濾 (ICMP Port Unreachable)。

代碼骨架

Server (接收端)


int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in servaddr = { .sin_family=AF_INET, .sin_port=htons(9999), .sin_addr.s_addr=INADDR_ANY };
bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));

struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
char buf[1024];
while (1) {
    int n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &len);
    if (n > 0) { buf[n]=0; printf("From %s:%d -> %s\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port), buf); }
}

Client (發送端)


int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in servaddr = { .sin_family=AF_INET, .sin_port=htons(9999) };
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);

sendto(sockfd, "Hello UDP", 9, 0, (struct sockaddr*)&servaddr, sizeof(servaddr));

總結

sendto/recvfrom 是 UDP 編程核心 API。掌握「每包帶地址」、「邊界保持」、「不可靠」三大特性,是構建 DNS、NTP、流媒體、遊戲同步等高性能協議的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved