【Linux Day14 UDP网络通讯】

UDP网络通讯

UDP报文结构:

  • 16位源端口:用于记录发送端的端口号(占用两个字节)
  • 16位目的端口:用于记录接收端的端口号(占用两个字节)
  • 16位UDP长度:确定UDP报文总长度,(占用两个字节)
  • 16位UDP校验和:接收端会首先知道即将发送来的数据的报文总长度,等数据来了之后,将数据的UPD校验和和已经知道的正确的报文总长度对比,如果不相同,直接丢掉UDP数据。(占用两个字节)

UDP编程流程

客户端代码

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

int main()
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        exit(1);
    }
    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000); 
    
    char buff[128] = {0};
    while(1)
    {
        int len = sizeof(saddr);
        scanf("%s",buff);
        if(strcmp(buff,"end") == 0)
        {
            break;
        }
        sendto(sockfd,buff,128,0,(struct sockaddr *)&saddr,len);
        memset(buff,0,128);
        int n = recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
        printf("n=%d,buff=%s\n",n,buff);
    }
    close(sockfd);
}

服务器端

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

int main()
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        exit(1);
    }
    struct sockaddr_in saddr,caddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000); 
    int res = bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
    if(-1 == res)
    {
        exit(1);
    }
    char buff[128] = {0};
    while(1)
    {
        int len = sizeof(caddr);
        int n = recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
        printf("n=%d,buff=%s\n",n,buff);
        sendto(sockfd,"OK",2,0,(struct sockaddr *)&caddr,len);
        memset(buff,0,128);
    }
    close(sockfd);
}

代码运行结果:

将服务端代码此处修改如下

运行结果:

结论:

  • UDP 是无连接的(不需要类似TCP的事先进行connect操作),所以每次发送数据都需要指定对端的地址(IP 和端口)。recvfrom()接收数据,每次都需要传给该方法一个地址结构来存放发送端的地址。recvfrom()可以接收所有客户端发送给当前应用程序的数据,并不是只能接收某一个客户端的数据。
  • UDP是面向数据报:传输的形式都是以数据报,不可分割也不可合并,发送端应用程序每执行一次写操作,UDP 模块就将其封装成一个 UDP 数据报发送。接收端必须及时针对每一个 UDP 数据报执行读操作,否则就会丢包。并且,如果用户没有指定足够的应用程序缓冲区来读取 UDP 数据,则 UDP 数据将被截断。
  • UDP是不可靠的(没有类似于TCP一样的机制(应答机制,超时重传,滑动窗口))
相关推荐
路溪非溪6 分钟前
关于Linux内核中头文件问题相关总结
linux
Lovyk2 小时前
Linux 正则表达式
linux·运维
Fireworkitte3 小时前
Ubuntu、CentOS、AlmaLinux 9.5的 rc.local实现 开机启动
linux·ubuntu·centos
sword devil9004 小时前
ubuntu常见问题汇总
linux·ubuntu
ac.char4 小时前
在CentOS系统中查询已删除但仍占用磁盘空间的文件
linux·运维·centos
淮北也生橘126 小时前
Linux的ALSA音频框架学习笔记
linux·笔记·学习
iナナ7 小时前
传输层协议——UDP和TCP
网络·网络协议·tcp/ip·udp
华强笔记9 小时前
Linux内存管理系统性总结
linux·运维·网络
十五年专注C++开发9 小时前
CMake进阶: CMake Modules---简化CMake配置的利器
linux·c++·windows·cmake·自动化构建
phoenix098110 小时前
ansible部署lnmp-allinone
linux·运维·ansible