UDP通讯测试

news/2024/5/18 13:17:08 标签: udp, 单片机, 网络协议

参考资料:UNIX网络编程

实验平台:PC为client,RaspberryPi为server

基本类型和接口函数,参考man手册

    #include <sys/socket.h>

       struct sockaddr {
           sa_family_t     sa_family;      /* Address family */
           char            sa_data[];      /* Socket address */
       };

       #include <netinet/in.h>

       struct sockaddr_in {
           sa_family_t     sin_family;     /* AF_INET */
           in_port_t       sin_port;       /* Port number */
           struct in_addr  sin_addr;       /* IPv4 address */
       };

       struct in_addr {
           in_addr_t s_addr;
       };

       typedef uint32_t in_addr_t;
       typedef uint16_t in_port_t;


       #include <sys/socket.h>
       ssize_t sendto(int sockfd, const void buf[.len], size_t len, int flags,
                      const struct sockaddr *dest_addr,
                      socklen_t addrlen);
       
       ssize_t recvfrom(int sockfd, void buf[restrict .len], size_t len, int flags,
                        struct sockaddr *src_addr,
                        socklen_t *addrlen);
       
            
      #include <arpa/inet.h>
       int inet_pton(int af, const char *restrict src, void *restrict dst);
       
       const char *inet_ntop(int af, const void *restrict src, char dst[restrict .size], socklen_t size);

       
       
       
       #include <arpa/inet.h>

       int inet_pton(int af, const char *restrict src, void *restrict dst);

服务器端


#define SERV_PORT 9877 /* TCP and UDP */


void dg_echo(int sockfd, struct sockaddr *p_cli_addr, socklen_t addr_len)
{
    int  n;
    socklen_t len;

    char  mesg[MAXLINE];
    char addr[addr_len];

    for ( ; ; )
    {
        len = addr_len;
        n = recvfrom(sockfd, mesg, MAXLINE, 0, p_cli_addr, &len);

        if(len != 0)
        {
            inet_ntop(AF_INET, &((struct sockaddr_in *)p_cli_addr)->sin_addr, addr, len);
            printf("Received %d Bytes : %s From client %s\n", n, mesg, addr);
        }

        printf("Now send back!\n");
        fflush(stdout);

        sendto(sockfd, mesg, n, 0, p_cli_addr, len);
    }
}

void server_main(void)
{
    int sockfd;
    struct sockaddr_in  serv_addr, cli_addr;


    /* IPPROTO_IP = 0 */      /* Dummy protocol for TCP.  */
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd < 0)
    {
        perror("socket fail");
    }
    else
    {
        memset(&serv_addr, 0, sizeof(serv_addr));

        serv_addr.sin_family = AF_INET;

        /* /usr/include/netinet/in.h */
        /* Address to accept any incoming messages.  */
        /* #define INADDR_ANY   ((in_addr_t) 0x00000000) */
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        //inet_pton(AF_INET, "192.168.39.39", &servaddr.sin_addr);
        serv_addr.sin_port = htons(SERV_PORT);

        bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

        dg_echo(sockfd, (struct sockaddr *)&cli_addr, sizeof(cli_addr));
    }
}

客户端

void dg_cli(FILE *fp, int sockfd, const struct sockaddr *p_serv_addr, socklen_t addr_len)
{
    int n;
    socklen_t len;

    struct sockaddr_in reply_addr;
    char sendline[MAXLINE];
    char recv_buf[MAXLINE + 1];
    char recv_addr[addr_len];

    while (fgets(sendline, MAXLINE, fp) != NULL)
    {
        sendto(sockfd, sendline, strlen(sendline), 0, p_serv_addr, addr_len);

        printf("send successfully!\n");
        fflush(stdout);

        n = recvfrom(sockfd, recv_buf, MAXLINE, 0, (struct sockaddr *)&reply_addr, &len);

        printf("receive success!\n");
        fflush(stdout);

        inet_ntop(AF_INET, &reply_addr.sin_addr, recv_addr, len);

        if((len != addr_len) || (memcmp(p_serv_addr, (struct sockaddr *)&reply_addr, len) != 0))
        {
            printf("Replied from %s ignored!\n", recv_addr);
            continue;
        }
        else
        {
            printf("Replied from %s with:\n", recv_addr);
        }

        recv_buf[n] = '\0';   /* null terminate */
        fputs(recv_buf, stdout);
    }
}

void client_main(const char *src)
{
    int  sockfd;
    struct sockaddr_in serv_addr;

    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);

    inet_pton(AF_INET, src, &serv_addr.sin_addr);

    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    if(sockfd < 0)
        perror("socket");
    else
    {
        printf("socket len: %ld\n", sizeof(serv_addr));
        dg_cli(stdin, sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    }

}

测试结果

客户端:

服务器:

补充知识:

程序员不应操作sockaddr结构,sockaddr是给操作系统用的
程序员应使用sockaddr_in来表示地址,sockaddr_in区分了地址和端口,使用更方便。


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

相关文章

Apache zookeeper kafka 开启SASL安全认证

背景&#xff1a;我之前安装的kafka没有开启安全鉴权&#xff0c;在没有任何凭证的情况下都可以访问kafka。搜了一圈资料&#xff0c;发现有关于sasl、acl相关的&#xff0c;准备试试。 简介 Kafka是一个高吞吐量、分布式的发布-订阅消息系统。Kafka核心模块使用Scala语言开发…

Flask学习(二):flask模板渲染

Flask没有自己模板引擎&#xff0c;使用的是 jinja2 模板引擎&#xff0c;可以帮助我们将数据渲染到各种格式的文档中&#xff0c;如 HTML、XML、Markdown 等。 中文文档地址&#xff1a;Jinja2中文文档_w3cschool 程序示例&#xff1a; from flask import Flask, render_te…

【TB作品】MSP430,波形发生器,单片机,Proteus仿真

文章目录 题目效果梯形波100个点产生方法锯齿波100个点产生方法c代码和proteus仿真 题目 114 波形发生器的制作 设计要求 设计一个能产生正弦波、方波、三角波、梯形波、锯齿波的波形发生器。设置5个开关K1~K5(从 上到下),分别对应正弦波、方波、三角波、梯形波、锯齿波,按一下…

Ypay源支付6.9无授权聚合免签系统可运营源码

YPay是一款专为个人站长设计的聚合免签系统&#xff0c;YPay基于高性能的ThinkPHP 6.1.2 Layui PearAdmin架构&#xff0c;提供了实时监控和管理的功能&#xff0c;让您随时随地掌握系统运营情况。 说明 Ypay源支付6.9无授权聚合免签系统可运营源码 已搭建测试无加密版本…

(C语言)strcmp函数详解与模拟实现与strncmp详解

目录 1. strcmp函数详解 2. strcmp模拟实现 3. strncmp函数 3.1 特殊情况分析 1. strcmp函数详解 头文件<string.h> 返回值是int类型&#xff0c;函数是将str1与str2这两个数组进行比较&#xff0c; 若str1>str2返回大于0的值 若str1<str2返回小于0的值 若s…

树莓派 ubuntu 23.10 mantic 换阿里云源

sudo nano /etc/apt/sources.list 如下内容直接替换 deb https://mirrors.aliyun.com/ubuntu-ports/ mantic main restricted universe multiverse deb-src https://mirrors.aliyun.com/ubuntu-ports/ mantic main restricted universe multiversedeb https://mirrors.aliyun.…

【机器学习300问】35、什么是随机森林?

〇、让我们准备一些训练数据 idx0x1x2x3x4y04.34.94.14.75.5013.96.15.95.55.9022.74.84.15.05.6036.64.44.53.95.9146.52.94.74.66.1152.76.74.25.34.81 表格中的x0到x4一共有5个特征&#xff0c;y是目标值只有0,1两个值说明是一个二分类问题。 关于决策树相关的前置知识&am…

vue中的属性的冒号:

说明 加冒号的&#xff0c;说明后面的是一个变量或者表达式&#xff1b; 没加冒号的后面就是对应的字符串字面量&#xff01; 例子&#xff1a; <el-radio-group v-model"handle"><el-radio :label"true">打开</el-radio><el-radio…