Linux 网络编程:UDP Socket 群聊模型实现与细节分析
本文基于 Linux 网络编程,使用 C/C++ 的 socket API,实现一个简单的 UDP 群聊程序,以加深对 UDP 通信模型的理解。
整体设计思路
Server 负责收消息、记住客户端并转发消息;Client 负责发消息和收广播。
Server 的核心职责
socket(AF_INET, SOCK_DGRAM):创建 UDP 套接字bind:占住一个众所周知的端口,等客户端来找recvfrom:接收数据,顺带感知客户端的 IP 和端口- 用
ip + port作为 key,维护一个在线用户表 - 每收到一条消息,就
sendto给所有用户 → 群聊效果
Client 的核心职责
- 不
bind,交给 OS 随机分配端口 - 一个线程:从标准输入读数据,
sendto发给 server - 一个线程:
recvfrom等 server 的广播消息
UDP 服务端
class Server {
public:
// 构造函数:保存 server IP 和端口号
Server(std::string server_ip, uint16_t server_port)
: server_ip_(server_ip), server_port_(server_port) {}
// 初始化 UDP socket 并完成 bind
void init() {
// 1. 创建 UDP socket
// AF_INET : IPv4
// SOCK_DGRAM : UDP(无连接、面向报文)
sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd_ < 0) {
printf("socket fail!\n");
exit(1);
}
printf("socket successful! socket:%d\n", sockfd_);
// 2. 填充本地地址结构
struct local;
(&local, (local));
local.sin_family = AF_INET;
local.sin_port = (server_port_);
local.sin_addr.s_addr = (server_ip_.());
address_len = (local);
((sockfd_, ( sockaddr *)&local, address_len) < ) {
();
();
}
();
}
{
std::string message = ;
message += client_ip;
message += ;
message += std::(client_port);
message += ;
message += info;
( user : users) {
(sockfd_, message.(), message.(), , ( sockaddr *)&user.second, (user.second));
}
}
{
() {
buffer[];
key[];
(buffer, , (buffer));
(key, , (key));
client;
(&client, client);
client_len = (client);
n = (sockfd_, buffer, (buffer) - , , (sockaddr *)&client, &client_len);
std::string client_ip = (client.sin_addr);
client_port = (client.sin_port);
(key, key, , client_ip.(), client_port);
is_exist = users.(key);
(is_exist == users.()) {
users.(std::(key, client));
();
}
(n > ) {
buffer[n] = ;
std::string info = buffer;
(info, client_ip, client_port);
}
}
}
~() {
(sockfd_ > ) {
(sockfd_);
}
}
:
std::string server_ip_;
server_port_;
sockfd_;
std::unordered_map<std::string, sockaddr_in> users;
};
{
Server* scr = (, );
scr->();
scr->();
}



