Linux编程(通信协议---udp)

    UDP(用户数据报协议)是一种无连接的网络协议,主要用于快速传输数据。以下是UDP协议的一些主要特点:

1. **无连接**:UDP是无连接的协议,这意味着在数据传输之前不需要建立连接。每个UDP数据包都是独立的,不需要前一个数据包的确认。

2. **简单性**:UDP的协议结构相对简单,只有8字节的UDP头部,包括源端口、目的端口、长度和校验和。

3. **快速性**:由于UDP不需要建立连接和进行数据确认,因此它的数据传输速度通常比TCP快。

4. **不保证可靠性**:UDP不保证数据的可靠传输,也就是说,数据包可能会丢失、重复或乱序到达。

5. **无拥塞控制**:UDP没有拥塞控制机制,这意味着它不会根据网络的拥堵情况调整数据传输速率。

6. **支持多播和广播**:UDP支持多播和广播数据传输,这使得它可以用于发送数据到多个接收者。

7. **校验和**:UDP包含一个校验和字段,用于检测数据在传输过程中是否出现错误。如果检测到错误,接收方可以选择丢弃该数据包。

8. **应用场景**:UDP通常用于那些对实时性要求高但可以容忍一定数据丢失的应用,如视频会议、在线游戏、DNS查询等。

9. **端口号**:UDP使用端口号来区分不同的服务或进程,每个UDP数据包都包含源端口和目的端口。

10. **数据报长度**:UDP数据报的长度可以是任意的,但最大长度受限于IP数据报的最大长度,通常是65507字节。
 


2、框架: C/S模式 

  服务器端  server:socket() ===>bind()===>recvfrom()===>close()
   客户端  client:socket() ===>bind()===>sendto() ===>close()


注意:socket()的参数需要调整。

      socket(PF_INET,SOCK_DGRAM,0);

  bind() 客户端是可选的,服务器端是必须选的。

1、int socket(int domain, int type, int protocol);
功能:程序向内核提出创建一个基于内存的套接字描述符

参数:domain  地址族,PF_INET == AF_INET ==>互联网程序
  PF_UNIX == AF_UNIX ==>单机程序
  type    套接字类型:
     SOCK_STREAM  流式套接字 ===》TCP   
  SOCK_DGRAM   用户数据报套接字===>UDP
  SOCK_RAW     原始套接字  ===》IP
  protocol 协议 ==》0 表示自动适应应用层协议。

返回值:成功 返回申请的套接字id
失败  -1;

2、int bind(int sockfd, struct sockaddr *my_addr, 
             socklen_t addrlen);
功能:如果该函数在服务器端调用,则表示将参数1相关
  的文件描述符文件与参数2 指定的接口地址关联,
  用于从该接口接受数据。

  如果该函数在客户端调用,则表示要将数据从
  参数1所在的描述符中取出并从参数2所在的接口
  设备上发送出去。

  注意:如果是客户端,则该函数可以省略,由默认
        接口发送数据。
参数:sockfd 之前通过socket函数创建的文件描述符,套接字id
  my_addr 是物理接口的结构体指针。表示该接口的信息。

  struct sockaddr      通用地址结构
  {
  u_short sa_family;  地址族
  char sa_data[14];   地址信息
  };

  转换成网络地址结构如下:
  struct _sockaddr_in    ///网络地址结构
  {
  u_short    sin_family; 地址族
  u_short    sin_port;   ///地址端口
  struct in_addr  sin_addr;   ///地址IP
  char    sin_zero[8]; 占位
  };

  struct in_addr
  {
  in_addr_t s_addr;
  }

  socklen_t addrlen: 参数2 的长度。
返回值:成功 0
失败  -1;

发送接收函数:
3、ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
         const struct sockaddr *dest_addr, socklen_t addrlen);

功能:用于UDP协议中向对方发送数据。
参数:sockfd  本地的套接字id
  buff    本地的数据存储,一般是要发送的数据。
  len     要发送的数据长度
  flags   要发送数据方式,0 表示阻塞发送。

  dest_addr: 必选,表示要发送到的目标主机信息结构体。
  addrlen :目标地址长度。

返回值:成功  发送的数据长度
    失败   -1;


4、ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                  struct sockaddr *src_addr, socklen_t *addrlen);

功能:用于UDP协议中获取对方发送的数据。
参数:sockfd 本地的套接字id
  buff   要存储数据的内存区,一般是数组或者动态内存。
  len    要获取的数据长度,一般是buff的大小。
  flags  获取方式,0 阻塞

  src_addr 可选,表示对方的地址信息结构体,
   如果为NULL,表示不关心对方地址。
  addrlen  对方地址信息结构体大小。
   如果对方地址是NULL,则该值也为NULL。
返回值:成功 接收到的数据长度
失败  -1;

《1》实现udp通信示例代码:

服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    while(1)
    {
        char buf[512]={0};
        recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);
        time_t tm;
        time(&tm);
        sprintf(buf,"%s %s",buf,ctime(&tm));
        sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);
    }
    close(sockfd);
    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);


int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");

    while(1)
    {
        char buf[512]="hello,this is udp test";
        sendto(sockfd,buf,strlen(buf),0,(SA)&ser,sizeof(ser));
        bzero(buf,sizeof(buf));
        recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
        printf("buf is %s\n",buf);
        sleep(1);
    }
    close(sockfd);
    return 0;
}

《2》udp实现文件传输

服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    //ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    ser.sin_addr.s_addr = INADDR_ANY;
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }
    while(1)
    {
        char buf[512]={0};
        int rd_ret = recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);
        if(0 == strcmp(buf,"^_^"))
        {
            break;
        }
        write(fd,buf,rd_ret);
        bzero(buf,sizeof(buf));
        strcpy(buf,"go on");
        sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);
    }
    close(sockfd);
    close(fd);
    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
typedef struct sockaddr * (SA);

int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");
    int fd = open("/home/linux/1.png",O_RDONLY);
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }
    char buf[512]={0};
    while(1)
    {
        bzero(buf,sizeof(buf));
        int rd_ret = read(fd,buf,sizeof(buf));
        if(0==rd_ret)
        {
            break;
        }
        sendto(sockfd,buf,rd_ret,0,(SA)&ser,sizeof(ser));
        bzero(buf,sizeof(buf));
        recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
    }
    
    bzero(buf,sizeof(buf));
    strcpy(buf,"^_^");
    sendto(sockfd,buf,3,0,(SA)&ser,sizeof(ser));
    close(sockfd);
    close(fd);
    return 0;
}

《3》udp实现小聊天室功能

服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
typedef enum {CMD_LOGIN,CMD_CHAT,CMD_LOGOUT}TYPE;
typedef struct 
{
    TYPE type;
    char name[50];
    char context[128];

}MSG;
typedef struct 
{
    struct sockaddr_in cli;
    int flag; // 0  free 1 occu
}LIST;
#define MAX 10
LIST list[MAX]={0};
int do_login(int sockfd,MSG* msg,struct sockaddr_in* cli)
{
    int i = 0 ;
    for(i=0;i<MAX;i++)
    {
        if(1 == list[i].flag )
        {
            sendto(sockfd,msg,sizeof(MSG),0,(SA)&list[i].cli,sizeof(list[i].cli));
        }
    }
    for(i=0;i<MAX;i++)
    {
        if(0 == list[i].flag )
        {
            list[i].flag =1;
            //list[i].cli = *cli;
            memcpy(&list[i].cli,cli,sizeof(*cli));
            break;
        }
    }
    return 0;
}

int do_chat(int sockfd, MSG* msg,struct sockaddr_in*cli)
{
     int i = 0 ;
    for(i=0;i<MAX;i++)
    {
        if(1 == list[i].flag && 0!=memcmp(&list[i].cli,cli,sizeof(*cli)) )
        {
            sendto(sockfd,msg,sizeof(MSG),0,(SA)&list[i].cli,sizeof(list[i].cli));
        }
    }
}
int do_logout(int sockfd, MSG* msg,struct sockaddr_in*cli)
{
    return 0;
}
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    MSG msg;
    while(1)
    {
        bzero(&msg,sizeof(msg));
        recvfrom(sockfd,&msg,sizeof(msg),0,(SA)&cli,&len);
        switch(msg.type)
        {
            case CMD_LOGIN:
                do_login(sockfd,&msg,&cli);
                break;
            case CMD_LOGOUT:
                do_logout(sockfd,&msg,&cli);
                break;
            case CMD_CHAT:
                do_chat(sockfd,&msg,&cli);
                break;
        
        }
    }
    close(sockfd);
    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
typedef enum {CMD_LOGIN,CMD_CHAT,CMD_LOGOUT}TYPE;
typedef struct 
{
    TYPE type;
    char name[50];
    char context[128];

}MSG;
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    socklen_t len = sizeof(cli);
    MSG msg;
    char name[50]={0};
    printf("input name:");
    fgets(name,sizeof(name),stdin);
    name[strlen(name)-1]='\0';

    msg.type = CMD_LOGIN;
    strcpy(msg.name ,name);
    strcpy(msg.context,"login");

    sendto(sockfd,&msg,sizeof(msg),0,(SA)&ser,sizeof(ser));

    pid_t pid = fork();
    if(pid>0)
    {
        while(1)
        {
            bzero(&msg,sizeof(msg));
            recvfrom(sockfd,&msg,sizeof(msg),0,NULL,NULL);    
            printf("%s:%s\n",msg.name,msg.context);
        }
    }
    else if(0==pid)
    {
        while(1)
        {
            printf("to all");    
            char buf[128]={0};
            strcpy(msg.name,name);
            msg.type = CMD_CHAT;
            fgets(msg.context,sizeof(msg.context),stdin);//#quit
            msg.context[strlen(msg.context)-1]='\0';
            if(0==strcmp(msg.context,"#quit"))
            {
                msg.type = CMD_LOGOUT;
                strcpy(msg.context,"CMD_LOGOUT");
            }
            sendto(sockfd,&msg,sizeof(msg),0,(SA)&ser,sizeof(ser));
        }
    }
    else 
    {
        perror("fork");
        exit(1);
    }
    close(sockfd);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/802169.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

remote: ERROR: commit b81ea84: missing Change-Id in message footer

首次拉取代码后,在本地已经编辑添加了代码并且想要提交到远端仓库 git add . git commit 当commit之后想要pull的时候报错了 git pull 执行到git pull 时出现这个问题,这是由于Change-Id没了,提示: ! [remote rejected] HEAD -> refs/for/master (commit b81ea84: mis…

git回退分支版本git reset --hard HEAD

git回退分支版本git reset --hard HEAD git reset --hard HEAD 上面命令清除本地所有修改&#xff0c;与下面相似&#xff1a; git reset --hard origin/master 等同于&#xff1a; git reset --hard HEAD~0 说明&#xff1a; HEAD 当前版本 HEAD^ 上一个版本 HEAD^^ 上上…

JVM---对象是否存活及被引用的状态

1.如何判断对象是否存活 1.1 引用计数算法 概念&#xff1a;在对象头部增加一个引用计数器,每当有一个地方引用它时&#xff0c;计数器值就加一&#xff1b;当引用失效时&#xff0c;计数器值就减一&#xff1b;任何时刻计数器为零的对象就是不可能再被使用的。 优点&#xff1…

LabVIEW学习-LabVIEW储存Excel表格

上述实现了将格式化的时间和正弦波的频率振幅相位以及正弦波数据输入到excel表格中。 下面介绍其中使用到的函数&#xff1a; 1. 所在位置&#xff0c;函数选板->定时->获取日期/时间(秒) 2. 将获取的时间进行格式化处理&#xff0c;输出格式化的日期/时间字符串。 函…

AI赋能基础设施巡检,技术革新助力水泥建筑缺陷检测分析,基于YOLOv8模型开发构建水泥建筑场景下裂缝缺陷分割检测识别系统

在现代化城市建设的宏伟蓝图中&#xff0c;公路、隧道、桥梁、大坝等水泥类基础设施如同城市的血脉&#xff0c;支撑着社会的正常运转与经济的蓬勃发展。然而&#xff0c;时间的侵蚀与自然的考验使得这些建筑不可避免地面临老化与损坏的问题&#xff0c;裂缝作为其中最为常见的…

AV1 编码标准环路滤波和后处理技术概述

AV1 环路滤波 去块滤波器 在视频编码的环路滤波管道中&#xff0c;去块滤波器&#xff08;deblocking filter&#xff09;用于减少量化引起的变换块边界处的块状伪影。 总结&#xff1a; 去块滤波器的应用&#xff1a; 对于亮度&#xff08;luma&#xff09;色度分量&#xff…

minIO集成springboot

问题 minIO与spring集成。 步骤 创建桶 创建key 找到创建账号页面&#xff0c;如下图&#xff1a; 点击创建&#xff0c;如下图&#xff1a; 设置如下权限&#xff1a; {"Version": "2012-10-17","Statement": [{"Effect": &q…

华为OD算法题汇总

60、计算网络信号 题目 网络信号经过传递会逐层衰减&#xff0c;且遇到阻隔物无法直接穿透&#xff0c;在此情况下需要计算某个位置的网络信号值。注意:网络信号可以绕过阻隔物 array[m][n]&#xff0c;二维数组代表网格地图 array[i][j]0&#xff0c;代表i行j列是空旷位置 a…

如何在所有docker命令前加上一个sudo

如果当前登录用户不是root不用&#xff0c;使用docker命令的时候&#xff0c;需要在前面加上一个sudo 提升权限。 但是每次都加&#xff0c;就感觉特别的麻烦&#xff0c;如何简化呢&#xff1f; 解决办法 打开你的shell配置文件&#xff08;例如&#xff0c;如果你使用bash&am…

Spring Cloud Eureka快读入门Demo

1.什么是Eureka&#xff1f; Eureka 由 Netflix 开发&#xff0c;是一种基于REST&#xff08;Representational State Transfer&#xff09;的服务&#xff0c;用于定位服务&#xff08;服务注册与发现&#xff09;&#xff0c;以实现中间层服务的负载均衡和故障转移&#xff…

C语言 | Leetcode C语言题解之第239题滑动窗口最大值

题目&#xff1a; 题解&#xff1a; int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize) {int prefixMax[numsSize], suffixMax[numsSize];for (int i 0; i < numsSize; i) {if (i % k 0) {prefixMax[i] nums[i];} else {prefixMax[i] fmax(pref…

甄选范文“论软件维护方法及其应用”软考高级论文,系统架构设计师论文

论文真题 软件维护是指在软件交付使用后,直至软件被淘汰的整个时间范围内,为了改正错误或满足 新的需求而修改软件的活动。在软件系统运行过程中,软件需要维护的原因是多种多样的, 根据维护的原因不同,可以将软件维护分为改正性维护、适应性维护、完善性维护和预防性 维护…

Mindspore框架CycleGAN模型实现图像风格迁移|(三)损失函数计算

Mindspore框架&#xff1a;CycleGAN模型实现图像风格迁移算法 Mindspore框架CycleGAN模型实现图像风格迁移|&#xff08;一&#xff09;CycleGAN神经网络模型构建 Mindspore框架CycleGAN模型实现图像风格迁移|&#xff08;二&#xff09;实例数据集&#xff08;苹果2橘子&…

JAVA 异步编程(异步,线程,线程池)一

目录 1.概念 1.1 线程和进程的区别 1.2 线程的五种状态 1.3 单线程,多线程,线程池 1.4 异步与多线程的概念 2. 实现异步的方式 2.1 方式1 裸线程&#xff08;Thread&#xff09; 2.1 方式2 线程池&#xff08;Executor&#xff09; 2.1.1 源码分析 2.1.2 线程池创建…

新的“SCALE”软件允许为 AMD GPU 原生编译 CUDA 应用程序

虽然已经有各种努力&#xff0c;如HIPIFY来帮助将CUDA源代码转换为AMD GPU的可移植C代码&#xff0c;然后是之前AMD资助的ZLUDA&#xff0c;允许CUDA二进制文件通过CUDA库的直接替代品在AMD GPU上运行&#xff0c;但有一个新的竞争者&#xff1a;SCALE。SCALE现在作为GPGPU工具…

超算网络体系架构-资源层-平台层-服务层-应用层

目录 超算网络体系架构 我国超算基础设施 超算互联网相关标准研制方面 技术架构 资源层 基础资源 芯片多样 体系异构 高效存储 高速互连 资源池化 可隔离 可计量 互联网络 高带宽 低时延 高安全 平台层 算力接入 资源管理 算力调度 用户管理 交易管理 模…

基于springboot和mybatis的RealWorld后端项目实战二之实现tag接口

修改pom.xml 新增tag数据表 SET FOREIGN_KEY_CHECKS0;-- ---------------------------- -- Table structure for tags -- ---------------------------- DROP TABLE IF EXISTS tags; CREATE TABLE tags (id bigint(20) NOT NULL AUTO_INCREMENT,name varchar(255) NOT NULL,PR…

VBA学习(21):遍历文件夹(和子文件夹)中的文件

很多时候&#xff0c;我们都想要遍历文件夹中的每个文件&#xff0c;例如在工作表中列出所有文件名、对每个文件进行修改。VBA给我们提供了一些方式&#xff1a;&#xff08;1&#xff09;Dir函数&#xff1b;&#xff08;2&#xff09;File System Object。 使用Dir函数 Dir…

2024年大数据高频面试题(中篇)

文章目录 Kafka为什么要用消息队列为什么选择了kafkakafka的组件与作用(架构)kafka为什么要分区Kafka生产者分区策略kafka的数据可靠性怎么保证ack应答机制(可问:造成数据重复和丢失的相关问题)副本数据同步策略ISRkafka的副本机制kafka的消费分区分配策略Range分区分配策略…

三级域名能申请SSL证书吗?

在当今互联网时代&#xff0c;SSL证书已经成为了保障网站安全的重要工具&#xff0c;企业会为网站部署SSL证书来实现HTTPS加密以保护传输数据安全。然而随着业务的增长以及交易规模的扩大&#xff0c;为了更好的管理业务和内容&#xff0c;企业会在主域名的基础上划分二级域名&…