本文設計基於 UDP 的群聊系統:客戶端發送消息到服務器,服務器廣播給所有在線客戶端。對比前作基於管道/select 的進程間通信,本文採用 Socket API 實現網絡級通信。
select 輪詢監聽 Sockettypedef struct sockaddr_in SA;
typedef struct client_tag {
SA ct_addr; // 客戶端地址信息
struct client_tag* ct_next;
} CNODE, *pcNODE; // 客戶端鏈表節點
#define TYPE_ON 1
#define TYPE_OFF 2
#define TYPE_CHAT 3
#define SIZE 1024
typedef struct msg_tag {
int msg_type; // 消息類型
int msg_len; // 實際長度
char msg_buf[SIZE]; // 消息內容
} MSG, *pMSG;
select 監聽 Socket 可讀事件recvfrom 獲取發送端地址與 MSG 結構msg_type 處理:
TYPE_ON:將客戶端地址加入鏈表TYPE_OFF:從鏈表移除TYPE_CHAT:遍歷鏈表 sendto 廣播給所有客戶端select// 服務器主循環
while(1) {
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
timeout.tv_sec = 1; timeout.tv_usec = 0;
int ret = select(sockfd+1, &readfds, NULL, NULL, &timeout);
if(ret <= 0) continue; // 超時或錯誤
if(FD_ISSET(sockfd, &readfds)) {
socklen_t addrlen = sizeof(SA);
MSG msg;
SA cli_addr;
recvfrom(sockfd, &msg, sizeof(MSG), 0, (struct sockaddr*)&cli_addr, &addrlen);
switch(msg.msg_type) {
case TYPE_ON: add_client(&head, cli_addr); break;
case TYPE_OFF: del_client(&head, cli_addr); break;
case TYPE_CHAT: broadcast(sockfd, head, &msg, cli_addr); break;
}
}
}
TYPE_ON 到服務器recvfrom 顯示消息TYPE_CHATTYPE_OFF| 特性 | UDP 方案 | TCP 方案 |
|---|---|---|
| 連接管理 | 無連接,靠應用層心跳/上下線包 | 長連接,斷開即下線 |
| 可靠性 | 應用層實現 ACK/重傳(可選) | 內建可靠傳輸 |
| 廣播效率 | 單發多收,需遍歷發送 | 同樣需遍歷 |
| NAT 穿透 | 較易配合 STUN/TURN | 需保持連接 |
| 適用場景 | 局域網、弱實時性、廣播業務 | 可靠性要求高、長連接業務 |