【Linux】Socket编程UDP
📌 相关专栏
- 【Linux专栏】
- 【C语言专栏】
- 【测试专栏】
📌 相关文章推荐
- 【测试】一文读懂软件测试:新手真正需要的测试认知
- 【Linux】网络基础2---Socket编程预备
- 【C语言】超实用VS调试干货,新手也能轻松排错
文章目录
- 一、套接字的种类
- 1. 流式套接字 (SOCK_STREAM)
- 2. 数据报套接字 (SOCK_DGRAM)
- 3. 原始套接字 (SOCK_RAW)
- 4. Unix域套接字 (Unix Domain Socket)
- 二、再来认识一下UDP
- 1. 核心特性(对比 TCP )
- 三、UDP编程
- 1. 服务端
- 2. 客户端
- 实施步骤
- 1.连接并确认环境
- 2. 创建代码文件
- 3. 写入代码(代码在上面)
- 4. 编译
- 5. 运行测试
- 6. 运行结果
- 7.可能遇到的问题
- 7. 验证是否通过
- 8. 测试脚本
一、套接字的种类
1. 流式套接字 (SOCK_STREAM)
- 协议:
基于 TCP,提供面向连接、可靠的数据传输服务。 - 特点:保证数据按顺序到达且无差错,类似打电话。适用于网页浏览、文件下载、邮件收发等对数据准确性要求高的场景。
2. 数据报套接字 (SOCK_DGRAM)
- 协议:
基于 UDP,提供无连接、不可靠的服务。 - 特点:每个数据包独立发送,不保证顺序或可靠到达,但传输效率高。类似寄信。适用于实时性要求高的场景,如视频会议、在线游戏、DNS查询。
3. 原始套接字 (SOCK_RAW)
- 协议:允许直接访问和操作底层协议(如IP、ICMP)。
- 特点:可以构造自定义的数据包或读取网络上的原始数据包。主要用于网络诊断(如Ping命令)和网络安全工具开发(如Wireshark、Nmap)。
4. Unix域套接字 (Unix Domain Socket)
- 协议:
不基于TCP/UDP网络协议,专门用于同一台设备上不同进程间的通信(IPC)。 - 特点:效率极高,比网络套接字更快。通常通过文件系统中的一个文件来表示(例如 /var/run/docker.sock)。常用于数据库(如MySQL)、Docker守护进程等高性能本地通信。
二、再来认识一下UDP
UDP(User Datagram Protocol,用户数据报协议)是 TCP 的“简单粗暴”版兄弟。用一句话概括:它是“只管发,不管到”的明信片服务。
1. 核心特性(对比 TCP )
| 特性 | UDP | TCP |
|---|---|---|
| 连接状态 | 无连接(直接发) | 面向连接(先握手) |
| 可靠性 | 不可靠(发完就忘) | 可靠(确认+重传) |
| 顺序保证 | 不保证(可能乱序) | 保证按序到达 |
| 数据边界 | 有边界(数据报) | 无边界(字节流) |
| 速度 | 快(无开销) | 慢(握手、确认、拥塞控制) |
| 头部大小 | 8 字节 | 20-60 字节 |
| 流量控制 | 无 | 有 |
| 拥塞控制 | 无 | 有 |
| 单次发送上限 | 约 64KB | 无限制(流式) |
三、UDP编程
1. 服务端
所需类型:
int_sockfd;//创建套接字对应的文件描述符uint_16t _port;//端口号string _ip;//服务端的IP地址 bind 0 表示绑定任意地址bool _isrunning;//判断服务端是否在进行示例:最简单的UDP服务端(接收数据并回显)这里我用的是xshell
//udp_server.c#include <stdio.h>#include <string.h>#include <arpa/inet.h>int main(){int sockfd = socket(AF_INET,SOCK_DGRAM,0);struct sockaddr_in addr ={.sin_family = AF_INET,.sin_port = htons(8888),.sin_addr.s_addr = INADDR_ANY};bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));char buf[1024];struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&client_addr,&len);printf("收到: %s\n",buf);sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&client_addr,len);close(sockfd);return0;}2. 客户端
//client.c#include <stdio.h>#include <string.h>#include <arpa/inet.h>int main(){int sockfd = socket(AF_INET,SOCK_DGRAM,0);struct sockaddr_in server_addr ={.sin_family = AF_INET,.sin_port = htons(8888)};inet_pton(AF_INET,"127.0.0.1",&server_addr.sin_addr);char*msg ="Hello UDP";sendto(sockfd,msg,strlen(msg),0,(struct sockaddr*)&server_addr,sizeof(server_addr));char buf[1024];socklen_t len = sizeof(server_addr);recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&server_addr,&len);printf("收到回复: %s\n",buf);close(sockfd);return0;}实施步骤
1.连接并确认环境
# 连上后确认 GCC 是否安装gcc--version# 如果没有,安装 GCC(Ubuntu/Debian 用 apt,CentOS 用 yum)sudoaptupdate&&sudoaptinstallgcc-y# Ubuntu/Debian# sudo yum install gcc -y # CentOS/RedHat这里不懂的可以看前面的博客文章:https://blog.csdn.net/2502_91546643/article/details/160417745?spm=1011.2415.3001.10575&sharefrom=mp_manage_link
2. 创建代码文件
- touch:先创建一个空白文件
- vim 文件名:
- 如果文件不存在,就自动帮你新建一个空文件,并直接进入编辑;
- 如果文件已存在,就直接进入编辑
# 创建两个文件 //这里用touchtouchudp_server.c udp_client.c3. 写入代码(代码在上面)
#因为上面已经创建了这两个文件,所以是直接进入编辑vimudp_server.cvimudp_client.c按i进入编辑模式,按ESC退回命令模式,在输入:wq保存退出
4. 编译
# 生成服务端和客户端程序gcc udp_server.c-oserver gcc udp_client.c-oclient5. 运行测试
./udp_server&./udp_client //这是只有一个Xhsell窗口的情况下6. 运行结果
7.可能遇到的问题
问题1:端口被占用
# 换个端口,修改代码里的 8888 为其他数字(如 9999)# 改完重新编译问题2:收不到数据
# 检查防火墙(云服务器安全组要放行 UDP 端口)sudoufw status# 查看防火墙状态sudoufw allow8888/udp# 开放 UDP 8888 端口# 如果是云服务器(阿里云/腾讯云等),还需要在控制台安全组规则中放行 UDP 8888问题3:想停掉后台服务端
# 查找进程并杀掉psaux|grepserverkill<进程ID>7. 验证是否通过
即上面的运行结果:
8. 测试脚本
(1)创建一个test.sh文件
touchtest.sh(2)对test.sh文件进行编辑:
vimtest.sh输入以下内容:
gcc udp_server.c-oserver&&gcc udp_client.c-oclientecho"编译成功,请运行 ./server 和 ./client"(3)赋予执行权限(普通用户没有该执行权限)
赋予权限前:
赋予权限后:输入chmod +x test.sh
