UDP通信机制详解

简介: UDP通信机制详解

1. UDP通信流程

前面介绍了TCP,TCP是面向连接的、安全的、流式传输协议。UDP是面向无连接的、不安全的、报式传输协议。UDP通信流程如下:

  • 服务器端:
  • 创建套接字 - socket
  • 第二个参数使用SOCK_DGRAM,表示报式协议,即UDP。TCP使用的是SOCK_STREAM。
  • 绑定IP和端口:bind
  • fd
  • struct sockaddr —— 服务器
  • 通信
  • 接收数据:recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
  • 同accept的第2、3个参数使用方法相同。
  • sockfd:文件描述符
  • buf:接收数据缓冲区
  • len:buf的最大容量
  • flags:0
  • src_addr:另一端的IP和端口, 传出参数
  • addrlen:传入传出参数
  • 发送数据: sendto
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
  • sockfd:socket函数创建出来的
  • buf:存储发送的数据
  • len:发送的数据的长度,注意是发送数据的大小,而不是buf的大小 strlen()。
  • flags:0
  • dest_addr:另一端的IP和端口
  • addrlen:dest_addr长度
  • UDP服务器端:需要一个套接字, 通信
  • 客户端:
  • 创建一个用于通信的套接字:socket
  • 通信
  • 发送数据:sendto,如果发送的数据太大,sendto会调用失败,UDP报文的长度是有上限的。
  • 需要先准备好一个结构体:struct sockaddr_in
  • 存储服务器的IP和端口
  • 接收数据:recvform
  • udp的数据是不安全的, 容易丢包
  • 丢包, 丢全部还一部分?
  • 只能丢全部,不存在只丢一部分的情况
  • 优点: 效率高

UDP通信流程示意图如下

2. 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 socket
    int 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 port
        sendto(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;
}

3. 心跳包

UDP是无连接的通信协议,那么如何去判断客户端和服务端是否处于连接状态呢?这就是心跳机制:

  • 心跳机制
  • 不会携带大量的数据
  • 每隔一定时间 服务器 → 客户端 / 客户端→服务器 发送一个数据包
  • 心跳包看成一个协议
  • 应用层协议
  • 判断网络是否断开
  • 有多个连续的心跳包没收到或没有回复
  • 关闭通信的套接字
  • 重连
  • 重新初始套接字
  • 继续发送心跳包
  • 乒乓包
  • 比心跳包携带的数据多一些
  • 除了知道连接是否存在,还能获取一些信息

如何理解心跳包呢——比如说,坐火车过隧道的时候,微信会提示服务器已断开连接,通过隧道后,微信会自己连上服务器。微信是如何知道和服务器断开连接了呢?就是通过心跳包机制。

比如,提前约定好,每隔多少秒客服端向服务器发1,如果服务器收到1,则回复客户端2,客户端收到2再发1,如此循环。如果客户端发送完1没有收到服务器回复的2,那么客户端将会再次发送1,测试几次如果依然没有回复,那么客户端会提示“服务器已断开连接”。

心跳包只能判断有没有连接,而乒乓包可以携带一些数据。

乒乓包——比如微信,如果有人给你发消息,或者有人发布朋友圈,给你点赞,都会有一个小红点提示,那么你的手机微信是怎么知道有人给你点赞,有人发朋友圈的呢?就是通过乒乓包不停的去询问。但是乒乓包也不是能携带所有数据,我们看到小红点,得点进去,然后手机客户端向服务器请求数据才能看到具体发了啥内容,评论了啥内容。心跳包只能判断是否连接,乒乓包可以携带少量提示信息。

4. TCP/UDP应用场景

  • TCP使用场景
  • 对数据安全性要求高的时候
  • 登录数据的传输 —— 比如用户名密码
  • 文件传输
  • HTTP协议
  • 传输层协议 —— TCP
  • UDP使用场景
  • 效率高 —— 实时性要求比较高
  • 视频聊天、直播
  • 通话
  • 有实力的大公司
  • 使用UDP
  • 在应用层自定义协议来做数据校验,既保证了传输效率,又保证了不丢数据。

相关文章
|
2月前
|
网络协议 Linux 网络性能优化
Linux C/C++之TCP / UDP通信
这篇文章详细介绍了Linux下C/C++语言实现TCP和UDP通信的方法,包括网络基础、通信模型、编程示例以及TCP和UDP的优缺点比较。
44 0
Linux C/C++之TCP / UDP通信
|
7月前
|
网络协议 算法 Java
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
78 3
|
3月前
|
C语言
C语言 网络编程(七)UDP通信创建流程
本文档详细介绍了使用 UDP 协议进行通信的过程,包括创建套接字、发送与接收消息等关键步骤。首先,通过 `socket()` 函数创建套接字,并设置相应的参数。接着,使用 `sendto()` 函数向指定地址发送数据。为了绑定地址,需要调用 `bind()` 函数。接收端则通过 `recvfrom()` 函数接收数据并获取发送方的地址信息。文档还提供了完整的代码示例,展示了如何实现 UDP 的发送端和服务端功能。
|
4月前
|
网络协议 数据处理 C语言
网络编程进阶:UDP通信
网络编程进阶:UDP通信
240 0
|
5月前
|
网络协议 网络架构
【网络编程入门】TCP与UDP通信实战:从零构建服务器与客户端对话(附简易源码,新手友好!)
在了解他们之前我们首先要知道网络模型,它分为两种,一种是OSI,一种是TCP/IP,当然他们的模型图是不同的,如下
211 1
|
5月前
|
网络协议 Java 数据处理
(一)Java网络编程之计网基础、TCP-IP协议簇、TCP、UDP协议及腾讯QQ通信原理综述
就目前而言,多数网络编程的系列的文章都在围绕着计算机网络体系进行阐述,但其中太多理论概念,对于大部分开发者而言,用途甚微。因此,在本系列中则会以实际开发者的工作为核心,从Java程序员的角度出发,详细解读Java的网络编程核心内容。
104 0
|
7月前
|
网络协议 安全 Java
网络编程、网络编程的三要素、TCP/UDP通信、三次握手和四次挥手
网络编程、网络编程的三要素、TCP/UDP通信、三次握手和四次挥手
65 1
网络编程、网络编程的三要素、TCP/UDP通信、三次握手和四次挥手
|
6月前
UDP通信
UDP通信
40 1
|
5月前
基于QT实现的QQ聊天简易版(UDP通信版)
源码已经给小伙伴们整理好了,微信搜索 嵌入式工程之家 关注公众号回复 QQ 即可获得源码和详细操作指示哦~
111 0
|
网络协议 Java
Java UDP通信详解
UDP(User Datagram Protocol)是一种无连接的网络传输协议,它不像TCP那样需要建立连接和维护状态,因此更加轻量级。UDP适用于那些对数据传输的实时性要求较高,可以容忍一定数据丢失的场景。本文将详细介绍Java中如何使用UDP协议进行网络通信,包括UDP套接字、数据传输、服务器和客户端的创建等。
194 0