《Linux C 实现 UDP 客户端与服务器》
1 简介
本文演示在 Linux 下用 C 语言实现基于 UDP 的 client/server:client 发送数据,server 回显后返回。UDP 属于无连接传输,编程上比 TCP 简单,只需 socket + bind + recvfrom/sendto。
2 服务器端
2.1 server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* 监听端口 */
#define MAXDATASIZE 100
int main()
{
int sockfd;
struct sockaddr_in server;
struct sockaddr_in client;
socklen_t addrlen;
int num;
char buf[MAXDATASIZE];
/* 创建 UDP socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("failed to create socket.");
return 1;
}
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY); /* 绑定所有本机地址 */
if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1) {
perror("failed to bind address.");
return 1;
}
addrlen = sizeof(client);
while (1) {
/* 阻塞接收,client 参数带回发端地址与端口 */
num = recvfrom(sockfd, buf, MAXDATASIZE, 0,
(struct sockaddr *)&client, &addrlen);
if (num < 0) {
perror("failed to receive msg from client.");
return 1;
}
buf[num] = '\0';
printf("got a message [%s] from client.\n"
"It's ip is %s, port is %d.\n",
buf, inet_ntoa(client.sin_addr), ntohs(client.sin_port));
/* 回显给发送方 */
sendto(sockfd, buf, sizeof(buf), 0,
(struct sockaddr *)&client, addrlen);
if (!strncmp(buf, "bye", 3))
break;
}
close(sockfd);
return 0;
}
2.2 编译运行
gcc server.c -o udpserver
./udpserver
3 客户端
3.1 client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 1234 /* 服务器监听端口 */
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in server;
socklen_t addrlen;
int num;
char buf[MAXDATASIZE];
if (argc < 3) {
fprintf(stderr, "usage: %s <server-ip> <message>\n", argv[0]);
return 1;
}
/* 创建 UDP socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("failed to create socket.");
return 1;
}
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (inet_pton(AF_INET, argv[1], &server.sin_addr) <= 0) {
perror("invalid server ip");
return 1;
}
strncpy(buf, argv[2], sizeof(buf) - 1);
addrlen = sizeof(server);
/* 发送数据(无需 connect) */
if (sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *)&server, addrlen) < 0) {
perror("failed to send.");
return 1;
}
/* 阻塞等待服务器回显 */
num = recvfrom(sockfd, buf, MAXDATASIZE, 0,
NULL, NULL);
if (num < 0) {
perror("failed to receive.");
return 1;
}
buf[num] = '\0';
printf("echo from server: [%s]\n", buf);
close(sockfd);
return 0;
}
3.2 编译运行
gcc client.c -o client
./client 127.0.0.1 hello
4 说明
- 服务端收到
bye前缀消息后退出循环并关闭 socket; - UDP 发送没有连接概念,
sendto中必须带上对端地址; recvfrom的src/fromlen参数可填NULL表示不关心来源。
5 参考文档
阅读 —
·
全站 —