22.UDP通信
22.UDP通信
TCP:传输控制协议,面向连接的,稳定的,可靠的,安全的数据流传递
稳定和可靠: 丢包重传
数据有序: 序号和确认序号
流量控制: 滑动窗口
UDP:用户数据报协议
面向无连接的,不稳定,不可靠,不安全的数据报传递---更像是收发短信
UDP传输不需要建立连接,传输效率更高,在稳定的局域网内环境相对可靠
UDP通信相关函数介绍:
ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
函数说明: 接收消息
参数说明:
▶sockfd 套接字
▶buf 要接受的缓冲区
▶len 缓冲区的长度
▶flags 标志位 一般填0
▶src_addr 原地址 传出参数
▶addrlen 发送方地址长度
▶返回值
成功: 返回读到的字节数
失败: 返回 -1 设置errno
调用该函数相当于TCP通信的recv+accept函数
函数说明: 发送数据
参数说明:
▶sockfd 套接字
▶dest_addr 目的地址
▶addrlen 目的地址长度
▶返回值
成功: 返回写入的字节数
失败: 返回-1,设置errno
UDP的服务器编码流程:
▶创建套接字socket,type=SOCK_DGRAM
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixedmaximum length).
▶绑定ip和端口 -bind
▶while循环收发数据
while (1)
{
//读取消息
recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &len);
//发送数据
sendto(cfd, buf, n, 0, (struct sockaddr *)&client, len);
}
▶关闭套接字--close
close(cfd);
UDP客户端流程:
▶创建套接字socket,type=SOCK_DGRAM
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixedmaximum length).
▶while循环收发数据
while (1)
{
//发送数据
sendto(cfd, buf, n, 0, (struct sockaddr *)&client, len);
//读取消息
n = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &len);
}
▶关闭套接字--close
close(cfd);
编写udp代码并进行测试
测试:
多开器几个客户端经过测试表明:udp天然支持多客户端,这点和TCP不同,TCP需要维护连接。
使用nc命令进行测试: nc -u 127.1 8888
服务端
//udp服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
int main()
{
//创建socket
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd<0)
{
perror("socket error");
return -1;
}
//绑定
struct sockaddr_in serv;
struct sockaddr_in client;
bzero(&serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(cfd, (struct sockaddr *)&serv, sizeof(serv));
int i;
int n;
socklen_t len;
char buf[1024];
while(1)
{
//读取数据
memset(buf, 0x00, sizeof(buf));
len = sizeof(client);
n = recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr *)&client, &len);
//将大写转换为小写
for(i=0; i<n; i++)
{
buf[i] = toupper(buf[i]);
}
//printf("[%d]:n==[%d], buf==[%s]\n", ntohs(client.sin_port), n, buf);
//发送数据
sendto(cfd, buf, n, 0, (struct sockaddr *)&client, len);
}
//关闭套接字
close(cfd);
return 0;
}
终端1
终端2
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ nc -u 127.1 8888
nihao
NIHAO
终端3
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ netstat -anp | grep 8888
(并非所有进程都能被检测到,所有非本用户的进程信息将不会显示,如果想看到所有信息,则必须切换到 root 用户)
udp 0 0 127.0.0.1:36759 127.0.0.1:8888 ESTABLISHED 2991/nc
udp 0 0 0.0.0.0:8888 0.0.0.0:* 2990/./01-udp_server
终端4
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ nc -u 127.1 8888
shenme
SHENME
可以接受两个客户端。
两个客户端给服务端发送数据,收到谁的就发给谁。不会出现客户端A发给服务端同时服务端发给客户端B。
下面代码去掉注释
printf("[%d]:n==[%d], buf==[%s]\n", ntohs(client.sin_port), n, buf);
终端1
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ ./01-udp_server
[60231]:n==[4], buf==[SFS
]
[49824]:n==[12], buf==[SDFWSADFASD
]
终端2
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ nc -u 127.1 8888
sfs
SFS
终端3
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ nc -u 127.1 8888
sdfwsadfasd
SDFWSADFASD
客户端
//udp客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
int main()
{
//创建socket
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd<0)
{
perror("socket error");
return -1;
}
int n;
char buf[1024];
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
while(1)
{
//读标准输入数据
memset(buf, 0x00, sizeof(buf));
n = read(STDIN_FILENO, buf, sizeof(buf));
//发送数据
sendto(cfd, buf, n, 0, (struct sockaddr *)&serv, sizeof(serv));
//读取数据
memset(buf, 0x00, sizeof(buf));
n = recvfrom(cfd, buf, sizeof(buf), 0, NULL, NULL);
printf("n==[%d], buf==[%s]\n", n, buf);
}
//关闭套接字
close(cfd);
return 0;
}
终端1服务端
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ make 01-udp_server
cc 01-udp_server.c -o 01-udp_server
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ ./01-udp_server
[38049]:n==[6], buf==[NIHAO
]
终端2客户端1
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ ./02-udp-client
nihao
^C
cmt@cmt-VMware-Virtual-Platform:~/C_Program/day12$ ./02-udp-client
nihao
n==[6], buf==[NIHAO
]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)