UDP通信发送和接收 || UDP实现全双工通信

news/2024/5/18 12:36:00 标签: udp, 网络协议, 网络

recvfrom


    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
    功能:
        从套接字中接收数据
    参数:
        sockfd:套接字文件描述符
        buf:存放数据空间首地址
        flags:属性 默认为0 
        src_addr:存放IP地址信息的空间首地址
        addrlen:存放接收到IP地址大小空间的首地址
    返回值:
        成功返回实际接收字节数
        失败返回-1 

修改虚拟机到桥接模式

    点击"虚拟机"
    点击"设置"
    点击"网络适配器"
    选择"桥接模式"
    点击"确定"

3.将网卡桥接到无线网卡
    点击"编辑"
    点击"虚拟网络编辑器"
    点击"更改设置"

4.在Ubuntu中重启网络服务
    sudo /etc/init.d/networking restart 

    ifconfig

bind 
    int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
    功能:
        在套接字上绑定一个IP地址和端口号
    参数:
        sockfd:套接字文件描述符
        addr:绑定IP地址空间首地址
        addrlen:绑定IP地址的长度
    返回值:
        成功返回0 
        失败返回-1 

UDP需要注意的细节点:

    1.UDP是无连接,发端退出,收端没有任何影响
    2.UDP发送数据上限,最好不要超过1500个字节
    3.UDP是不安全不可靠的,连续且快速的传输数据容易产生数据丢失

UDP包头长度:8个字节
    源端口号(2个字节)
    目的端口号(2个字节)
    长度(2个字节)
    校验和(2个字节)

wireshark

 抓包工具

  操作流程:
    1.sudo wireshark
      打开wireshark抓包工具
    2.选择抓取数据包的网卡
      any
    3.执行通信的代码
    4.停止通信
    5.设定过滤条件
        ip.addr == IP地址 
        udp 
        tcp 
        udp.port == 端口
 

使用UDP实现文件的发送

发送端代码:

/*************************************************************************
	> File Name: recv_file.c
	> Author: yas
	> Mail: rage_yas@hotmail.com
	> Created Time: Wed 06 Mar 2024 02:11:43 PM CST
 ************************************************************************/

#include<stdio.h>
#include "head.h"
int main(void)
{
    int sockfd = 0;
    struct sockaddr_in sendaddr;
    ssize_t nret = 0;
    char filename[1024] = {0};
    int pf = 0;
    char tmpbuff[1024] = {0};
    int nbyte = 0;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("fail to socket");
        return -1;
    }


    fgets(filename, sizeof(filename), stdin);

    sendaddr.sin_family = AF_INET;
    sendaddr.sin_port = htons(50000);
    sendaddr.sin_addr.s_addr = inet_addr("192.168.1.174");

    nbyte = sendto(sockfd, filename, strlen(filename), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));
    if (nbyte == -1)
    {
        perror("fail to sendto");
        return -1;
    }
    
    pf = open(filename, O_RDONLY);
    if (pf == -1)
    {
        perror("fail to open");
        return -1;
    }

    while(1)
    {
        memset (tmpbuff, 0, sizeof(tmpbuff));
        nret = read(pf, tmpbuff, sizeof(tmpbuff));
        if(nret <= 0)
        {
            break;
        }
        nret = sendto(sockfd, tmpbuff, nret, 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));
    }

    close(pf);
    close(sockfd);

    return 0;
}

接收端代码:



#include<stdio.h>
#include "head.h"
int main(void)
{
    int sockfd = 0;
    ssize_t nsize = 0;
    struct sockaddr_in recvaddr;
    struct sockaddr_in sendaddr;
    ssize_t nret = 0;
    char filename[1024] = {0};
    socklen_t addlen = sizeof(recvaddr);
    int pf = 0;
    char tmpbuff[1024] = {0};
    int retbind = 0;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("fail to socket");
        return -1;
    }


    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(50000);
    recvaddr.sin_addr.s_addr = inet_addr("192.168.1.174");

    retbind = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
    if (retbind == -1)
    {
        perror("fail to bind");
        return -1;
    }

    //printf("!!!!!!!!!!!\n");
    nsize = recvfrom(sockfd, filename, sizeof(filename), 0,(struct sockaddr *)&sendaddr, &addlen);
    if (-1 == nsize)
    {
        perror("fail to recvfrom");
        return -1;
    }
    //printf("!!!!!!!!!!!\n");
    //printf("filename = %s\n", filename);

    pf = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
    if (pf == -1)
    {
        perror("fail to open");
        return -1;
    }

    while(1)
    {
        memset (tmpbuff, 0, sizeof(tmpbuff));
        nret = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0,(struct sockaddr *)&recvaddr, &addlen);
        if (nret <= 0)
        {
            break;
        }
        write(pf, tmpbuff, nret);
    }

    close(pf);
    close(sockfd);

    return 0;
}

使用UDP实现两个主机间的全双工通信

/*************************************************************************
	> File Name: homework.c
	> Author: yas
	> Mail: rage_yas@hotmail.com
	> Created Time: Wed 06 Mar 2024 06:09:58 PM CST
 ************************************************************************/

#include<stdio.h>
#include "head.h"
struct cilent
{
    char name[32];
    char text[1024];
};

struct cilent mycilent;
struct cilent youcilent;

void *pthreadSend(void *arg)
{
    int sockid = 0;
    struct sockaddr_in recvaddr;
    int nret = 0;

    sockid = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockid == -1)
    {
        perror("fail to socket");
        return NULL;
    }
    
    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(50000);
    recvaddr.sin_addr.s_addr = inet_addr("192.168.1.152");

    scanf("%s", mycilent.name);
    nret = sendto(sockid, mycilent.name, sizeof(mycilent.name), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
    if (nret == -1)
    {
        perror("fail to sendto");
        return NULL;
    }

    while(1)
    {
        memset(mycilent.text, 0, sizeof(mycilent.text));
        scanf("%s", mycilent.text);
        nret = sendto(sockid, mycilent.text, sizeof(mycilent.text), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
        if (nret == -1)
        {
            perror("fail to sendto");
            return NULL;
        }

        if(strcmp(mycilent.text, ".quit") == 0)
        {
            break;
        }
    }

    close(sockid);
}

void *pthreadRecv(void *argv)
{
    int sockid = 0;
    struct sockaddr_in recvaddr;
    struct sockaddr_in getaddr;
    socklen_t addlen = sizeof(getaddr);
    int nret = 0;

    sockid = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockid == -1)
    {
        perror("fail to socket");
        return NULL;
    }
    
    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(50000);
    recvaddr.sin_addr.s_addr = inet_addr("192.168.1.174");
    
    bind(sockid, (struct sockaddr *)&recvaddr, sizeof(recvaddr));

    nret = recvfrom(sockid, youcilent.name, sizeof(youcilent.name), 0, (struct sockaddr *)&getaddr, &addlen);
    if (nret == -1)
    {
        perror("fail to sendto");
        return NULL;
    }

    while(1)
    {
        memset(youcilent.text, 0, sizeof(youcilent.text));
        nret = recvfrom(sockid, youcilent.text, sizeof(youcilent.text), 0, (struct sockaddr *)&getaddr, &addlen);
        if (nret == -1)
        {
            perror("fail to sendto");
            return NULL;
        }

        printf("%s(%s:%d)>%s\n", youcilent.name, inet_ntoa(getaddr.sin_addr), ntohs(getaddr.sin_port), youcilent.text);
        if(strcmp(youcilent.text, ".quit") == 0)
        {
            break;
        }
    }
    close(sockid);
}

int main(void)
{
    pthread_t Send;
    pthread_t Recv;

    pthread_create(&Send, NULL, pthreadSend, NULL);
    pthread_create(&Recv, NULL, pthreadRecv, NULL);

    pthread_join(Send, NULL);
    pthread_join(Recv, NULL);



    return 0;
}

使用线程实现并行收发


http://www.niftyadmin.cn/n/5411602.html

相关文章

x86 Ubuntu上编译eudev给龙芯loongarch64架构主机使用

1、下载eudev库eudev-master.zip&#xff0c;链接&#xff1a;eudev库官方地址 2、下载龙芯的交叉编译工具&#xff1a;loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.2.tar.xz&#xff0c;链接&#xff1a;龙芯交叉编译官方地址 3、交叉编译器环境搭建 (1)、…

Ubuntu 20.04 ROS1 与 ROS2 通讯

激光雷达和3d视觉传感器驱动很多都是基于ros1开发的&#xff0c;由于自己项目在ros2环境开发&#xff0c;需要获取从驱动出来的点云数据流&#xff0c;所以尝试订阅ros1出来的点云topic话题&#xff0c;固需要ros1与ros2之间建立通讯连接。 项目环境&#xff1a; Legion-Y7000…

安卓部分手机使用webview加载链接后白屏(Android低版本会出现的问题)

前言 大爷&#xff1a;小伙我这手机怎么打开你们呢这个是白屏什么都不显示。 大娘&#xff1a;小伙我这也是打开你们呢这功能&#xff0c;就是一个白屏什么也没有&#xff0c;你们呢的应用不会有病毒吧。 小伙&#xff1a;我的手机也正常&#xff1b; 同事&#xff1a;我的也正…

[云原生] K8s之pod控制器详解

Pod 是 Kubernetes 集群中能够被创建和管理的最小部署单元。所以需要有工具去操作和管理它们的生命周期,这里就需要用到控制器了。 Pod 控制器由 master 的 kube-controller-manager 组件提供&#xff0c;常见的此类控制器有 Replication Controller、ReplicaSet、Deployment、…

打家劫舍(java版)

&#x1f4d1;前言 本文主要是【动态规划】——打家劫舍(java版)的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一…

【JS】关于this的使用

this 前言一、this是什么&#xff1f;二、做什么&#xff1f;1.全局环境2.函数环境3.new实例对象4.apply、bind、call绑定4.1 apply()4.2 call()4.3 bind() 三、为什么用this&#xff1f;四、如何改变this&#xff1f;五、应用场景&#xff1f;总结 前言 痛点 经常写Vue项目&a…

微软亚太区AI智能应用创新业务负责人许豪,将出席“ISIG-AIGC技术与应用发展峰会”

3月16日&#xff0c;第四届「ISIG中国产业智能大会」将在上海中庚聚龙酒店拉开序幕。本届大会由苏州市金融科技协会指导&#xff0c;企智未来科技&#xff08;AIGC开放社区、RPA中国、LowCode低码时代&#xff09;主办。大会旨在聚合每一位产业成员的力量&#xff0c;深入探索A…

Node.js的诞生

Node.js是什么&#xff0c;为何产生的&#xff0c;解决的痛点是什么&#xff1f; 1.Node是什么&#xff1f; Node.js是一个基于Chrome V8引擎的JavaScript运行时环境。 JavaScript语言以前只能在浏览器端被解释并运行,而Node.js的出现帮助开发者使用JavaScript语言在后端/服…