《Linux C 实现 UDP 客户端与服务器》

《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 参考文档

阅读 — · 全站 —
🎸 我的歌单 0 首