UDP Socket C语言示例(Linux)
UDP 是无连接,SOCK_DGRAM,不用 connect(当然客户端也可以connect简化写法),用 sendto / recvfrom。
socket()
└─ setsockopt() // 可选,两边都有
└─ bind() // 两边都必须
├─ TCP: listen() → accept() → recv()/send() (面向连接)
└─ UDP: recvfrom()/sendto() (无连接,直接收发包)
udp_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
#define BUF_SIZE 1024
int main()
{
int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buf[BUF_SIZE];
// 1. 创建UDP socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // 监听本机所有网卡
server_addr.sin_port = htons(PORT);
// 2. bind绑定端口
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
close(sockfd);
exit(1);
}
printf("UDP server listen on port %d\n", PORT);
while (1) {
memset(buf, 0, BUF_SIZE);
// 接收数据,同时拿到客户端地址
ssize_t n = recvfrom(sockfd, buf, BUF_SIZE, 0,
(struct sockaddr *)&client_addr, &client_len);
if (n < 0) {
perror("recvfrom");
continue;
}
printf("recv from %s:%d, data: %s\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buf);
// 回显给客户端
sendto(sockfd, buf, n, 0,
(struct sockaddr *)&client_addr, client_len);
}
close(sockfd);
return 0;
}
udp_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8888
#define BUF_SIZE 1024
int main()
{
int sockfd;
struct sockaddr_in server_addr;
socklen_t server_len = sizeof(server_addr);
char buf[BUF_SIZE];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
perror("inet_pton");
close(sockfd);
exit(1);
}
printf("input message to send: ");
while (fgets(buf, BUF_SIZE, stdin)) {
// 发送到服务端
sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *)&server_addr, server_len);
memset(buf, 0, BUF_SIZE);
// 等待回显
ssize_t n = recvfrom(sockfd, buf, BUF_SIZE, 0, NULL, NULL);
if (n > 0) {
printf("server echo: %s\n", buf);
}
printf("input message to send: ");
}
close(sockfd);
return 0;
}
编译&运行
gcc udp_server.c -o udp_server
gcc udp_client.c -o udp_client
# 终端1
./udp_server
# 终端2
./udp_client
要点说明
- UDP 无连接,没有 listen / accept
recvfrom会拿到对端地址,回复时用这个地址sendto- 客户端不需要 bind,内核自动分配随机端口
- 不保证可靠,丢包、乱序都可能发生
- 客户端也可以调用
connect,之后直接用send/recv,不用每次填地址(只是在本地保存目标地址,不是建立连接)
补充:Python UDP 版本(如果你需要)
udp_server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", 8888))
print("udp server 8888")
while True:
data, addr = s.recvfrom(1024)
print(f"from {addr}: {data.decode()}")
s.sendto(data, addr)
udp_client.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
msg = input("> ")
s.sendto(msg.encode(), ("127.0.0.1", 8888))
data, _ = s.recvfrom(1024)
print("echo:", data.decode())
你想要 C++ / Java / Python / Android(JNI) 哪个版本?或者想要加上超时、多客户端、非阻塞版本?

4329

被折叠的 条评论
为什么被折叠?



