来源:互联网转载 | 更新日期:2023-09-10 19:49:25
欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。
专栏:《Linux从小白到大神》《网络编程》
前面介绍了TCP,TCP是面向连接的、安全的、流式传输协议。UDP是面向无连接的、不安全的、报式传输协议。UDP通信流程如下:
服务器端:
创建套接字 - socket
绑定IP和端口:bind
通信
接收数据:recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);同accept的第2、3个参数使用方法相同。
发送数据: sendto
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);UDP服务器端:需要一个套接字, 通信
客户端:
创建一个用于通信的套接字:socket
通信
发送数据:sendto,如果发送的数据太大,sendto会调用失败,UDP报文的长度是有上限的。
需要先准备好一个结构体:struct sockaddr_in
接收数据:recvform
udp的数据是不安全的, 容易丢包
丢包, 丢全部还一部分?
优点: 效率高
UDP通信流程示意图如下
server
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h>int main(int argc, const char* argv[]) {// 创建套接字int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd == -1){perror("socket error");exit(1);}// fd绑定本地的IP和端口struct sockaddr_in serv;memset(&serv, 0, sizeof(serv));serv.sin_family = AF_INET;serv.sin_port = htons(8765);serv.sin_addr.s_addr = htonl(INADDR_ANY);int ret = bind(fd, (struct sockaddr*)&serv, sizeof(serv));if(ret == -1){perror("bind error");exit(1);}struct sockaddr_in client;socklen_t cli_len = sizeof(client);// 通信char buf[1024] = {0};while(1){int recvlen = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &cli_len);if(recvlen == -1){perror("recvform error");exit(1);}printf("recv buf: %s\n", buf);char ip[64] = {0};printf("New Client IP: %s, Port: %d\n",inet_ntop(AF_INET, &client.sin_addr.s_addr, ip, sizeof(ip)),ntohs(client.sin_port));// 给客户端发送数据sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&client, sizeof(client));}close(fd);return 0; }client
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h>int main(int argc, const char* argv[]) {// create socketint fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd == -1){perror("socket error");exit(1);}// 初始化服务器的IP和端口struct sockaddr_in serv;memset(&serv, 0, sizeof(serv));serv.sin_family = AF_INET;serv.sin_port = htons(8765);inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);//把点分十进制字符串 "127.0.0.1" 转成整形,并存到&serv.sin_addr.s_addr中// 通信while(1){char buf[1024] = {0};fgets(buf, sizeof(buf), stdin);// 数据的发送 - server - IP portsendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&serv, sizeof(serv));// 等待服务器发送数据过来recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL); //服务器的IP和port已经在在初始化的时候知道了,传NULL即可printf("recv buf: %s\n", buf);}close(fd);return 0; }UDP是无连接的通信协议,那么如何去判断客户端和服务端是否处于连接状态呢?这就是心跳机制:
心跳机制
心跳包看成一个协议
判断网络是否断开
重连
乒乓包
如何理解心跳包呢——比如说,坐火车过隧道的时候,微信会提示服务器已断开连接,通过隧道后,微信会自己连上服务器。微信是如何知道和服务器断开连接了呢?就是通过心跳包机制。
比如,提前约定好,每隔多少秒客服端向服务器发1,如果服务器收到1,则回复客户端2,客户端收到2再发1,如此循环。如果客户端发送完1没有收到服务器回复的2,那么客户端将会再次发送1,测试几次如果依然没有回复,那么客户端会提示“服务器已断开连接”。
心跳包只能判断有没有连接,而乒乓包可以携带一些数据。
乒乓包——比如微信,如果有人给你发消息,或者有人发布朋友圈,给你点赞,都会有一个小红点提示,那么你的手机微信是怎么知道有人给你点赞,有人发朋友圈的呢?就是通过乒乓包不停的去询问。但是乒乓包也不是能携带所有数据,我们看到小红点,得点进去,然后手机客户端向服务器请求数据才能看到具体发了啥内容,评论了啥内容。心跳包只能判断是否连接,乒乓包可以携带少量提示信息。
TCP使用场景
对数据安全性要求高的时候
HTTP协议
UDP使用场景
效率高 —— 实时性要求比较高
有实力的大公司
Copyright © 网站出售-网站交易平台 版权信息
网站备案号:黔ICP备2023004141号