😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍网络编程入门知识:UDP协议、UDP客户端、UDP服务端 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:2024-02-29 09:23:52
本文未经允许,不得转发!!!
![]()
UDP协议是一个简单的传输层协议,在RFC 768 [Postel 1980]中有详细说明。应用进程往一个UDP套接字写入一个消息,该消息随后被封装( encapsulating)到一个UDP数据报,该UDP数据报进而又被封装到一个IP数据报,然后发送到目的地。UDP不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数据报只到达一次。
UDP协议的几个特点:
![]()
编写UDP客户端的步骤:
- 1、创建UDP套接字
socket:SOCK_DGRAM;- 2、准备UDP服务端ip和端口,bzero、inet_pton
- 3、使用
sendto、recvfrom交互数据;- 4、关闭套接字
// udpCli.c
// gcc udpCli.c -o udpCli
#include
#include
#include
#include
#include
int main()
{
// 1、创建UDP套接字socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
perror("socket error" );
// 2、准备服务端ip和端口
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (10086);
if (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0) // 设置本机IP为服务端IP
perror("inet_pton error");
// 3、使用 sendto、recvfrom 交互数据
if(sendto(sockfd, "Hello,I am udp client", strlen("Hello,I am udp client"), 0, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
perror("sendto error" );
char recvline[256];
int n = 0;
while ( (n = recvfrom (sockfd, recvline, sizeof(recvline), 0, NULL, NULL)) > 0)
{
recvline[n] = 0 ;/*null terminate */
printf("recv[%s]\n",recvline);
}
if (n < 0)
perror("read error" );
// 4、关闭
close(sockfd);
return 0;
}
socket 函数
#include /* See NOTES */
#include
int socket(int domain, int type, int protocol);
socket函数创建一个套接字描述符。man手册描述,socket创建一个通信端点并返回一个描述符。
domain指定通信域,使用了AF_INET,表示是IPv4 Internet protocols协议的。type指定套接字类型,使用``,表示TCP协议的套接字(提供有序、可靠、双向、基于连接的字节流。可以支持带外数据传输机制)。protocol指定了要与套接字一起使用的特定协议。通常,在给定的协议族中,只有一个协议支持特定的套接字类型,在这种情况下,协议可以指定为0。sendto函数
#include
#include
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
sendto 函数将数据发送到指定的IP地址,一般在UDP协议使用。前面三个参数跟write函数一致,第4个参数是一个标志,最后两个参数跟connect函数的后两个参数一样,用来指定对端IP和端口。
写一个长度为0的数据报是可行的。在UDP情况下,这会形成一个只包含一个IP首部(对于IPv4通常为20个字节,对于IPv6通常为40个字节)和一个8字节UDP首部而没有数据的IP数据报。
![]()
编写UDP服务端的步骤:
- 1、创建UDP套接字
socket:SOCK_DGRAM;- 2、准备服务端ip和端口;
- 3、绑定,
bind- 4、使用
sendto、recvfrom交互数据;- 5、关闭套接字
// udpSer.c
// gcc udpSer.c -o udpSer
#include
#include
#include
#include
#include
int main()
{
// 1、创建UDP套接字socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
perror("socket error" );
// 2、准备服务端ip和端口
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (10086);
servaddr.sin_addr.s_addr = INADDR_ANY; // 指定ip地址为 INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任一网络接口上接受客户端的连接
// 3、绑定 bind
if (bind(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
perror("bind error" );
// 4、使用 sendto、recvfrom 交互数据
printf("UdpSer sockfd=%d, start \n",sockfd);
char recvline[256];
while(1)
{
struct sockaddr_in cliaddr;
bzero(&cliaddr, sizeof(cliaddr));
socklen_t addrLen=sizeof(cliaddr);
int n = recvfrom(sockfd, recvline, sizeof(recvline), 0, (struct sockaddr*)&cliaddr, &addrLen);
if(n>0)
{
recvline[n] = 0 ;/*null terminate */
printf("recv sockfd=%d %d byte, [%s] addrLen=%d, cliIp=%s, cliPort=%d\n",
sockfd, n, recvline, addrLen, inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
sendto(sockfd, "Hello,I am udp server", strlen("Hello,I am udp server"), 0, (struct sockaddr*)&cliaddr, addrLen);
}
}
// 5、关闭
close(sockfd);
return 0;
}
tcp服务端相关函数有:socket、bind、recvfrom、sendto。socket、sendto函数可以参照上面 2.2 小节。
#include /* See NOTES */
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
#include
#include
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
read函数一样,第4个参数是一个标志,最后两个参数跟accept函数的后两个参数一样,用来获取对端IP和端口,addrlen是一个值-结果参数。![]()
👉本文主要介绍Linux下网络编程的基础知识,先是简单介绍一下UDP协议,然后给出一个UDP客户端、UDP服务端最简单的例子,最后介绍创建UDP客户端、UDP服务端需要用到的函数。

上面的UDP例子由于只演示最简单的方法,会存在的一些问题:
1、数据报丢失没处理。可以设置超时、应答等方法来增加可靠性。
2、没有验证收到的数据。没有验证发送者的IP、端口。

如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁