• 报式套接字通讯实例


    报式套接字通讯实例

    使用套接字通讯流程

    被动端(先运行)
    1、取得SOCKET
    2、给SOCKET取得地址
    3、收/发消息
    4、关闭SOCKET

    主动端
    1、取得SOCKET
    2、给SOCKET取得地址(可省略)
    3、发/收消息
    4、关闭SOCKET

    各部分代码实现

    proto.h代码如下:

    #ifndef PROTO_H__
    #define PROTO_H__
    
    //定义端口号
    #define RCVPORT     "1989"
    
    #define NAMESIZE    11
    
    //__attribute__((packed))表示结构体取消内存对齐
    struct msg_st
    {
        uint8_t name[NAMESIZE];
        uint32_t math;
        uint32_t chinese;
    }__attribute__((packed));
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    rcvder.c代码如下:

    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include "proto.h"
    
    #define IPSTRSIZE   40
    
    int main()
    {
    
        int sd;
        //定义我端的地址laddr
        struct sockaddr_in laddr,raddr;
        struct msg_st rbuf;
        socklen_t raddr_len;
        char ipstr[IPSTRSIZE];
    
        //使用AF_INET协议族中的默认协议(0),实现SOCK_DGRAM
        sd = socket(AF_INET,SOCK_DGRAM,0);
        if(sd < 0)
        {
            perror("socket()");
            exit(0);
        }
    
        laddr.sin_family = AF_INET;
        //因为端口要在网络传输,所以使用htons转换,将本地(host)转为网络(net),宽度为short
        laddr.sin_port = htons(atoi(RCVPORT));
        /*inet_pton将IP地址的点分式转为整数
        int inet_pton(int af,const char *src,void *dst)
        参数:
        af  协议族,要么是IPV4(AF_INET)要么是IPV6(AF_INET6)
        src 要转换的IP地址
        dst 转换后要放置的地址处
        */
        //"0.0.0.0"表示匹配的任意地址
        inet_pton(AF_INET,"0.0.0.0",&laddr.sin_addr);
    
        //我端的地址和地址长度
        if(bind(sd,(void *)&laddr,sizeof(laddr)) < 0)
        {
            perror("bind()");
            exit(1);
        }
    
        while(1)
        {
            /*
            ssize_t recv(int sockfd,void *buf,size_t len,int flags)
            这个适用于流式套接字,一对一通讯
            
            ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,
                            struct sockaddr *src_addr,socklen_t *addrlen)
            recvfrom是适用于报式套接字,非一对一的通讯,要记录传输数据地址从哪里来的
            */
           /*
           一定要初始化raddr_len的大小,否则回造成第一次打开地址不对,后面会对
    
           */
            raddr_len = sizeof(raddr);
            recvfrom(sd,&rbuf,sizeof(rbuf),0,(void *)&raddr,&raddr_len);
            //使用inet_ntop();函数将ip大整数转为点分式
            inet_ntop(AF_INET,&raddr.sin_addr,ipstr,IPSTRSIZE);
            printf("----MESSAGE FROM IP: %s port: %d---\n",ipstr,ntohs(raddr.sin_port));
            printf("NAME = %s\n",rbuf.name);
            printf("MATH = %d\n",ntohl(rbuf.math));
            printf("CHINESE = %d\n",ntohl(rbuf.chinese));
    
        }
    
    
        
        
        close(sd);
    
        exit(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    编译执行结果如下:

    使用netstat -anu命令查看udp网络状态,如果查看tcp使用netstat -ant命令,结果如下1989端口已经打开。

    1657706370492

    snder.c代码如下:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include "proto.h"
    
    int main(int argc,char *argv[])
    {
    
        int sd;
        //将待发送的内容放到sbuf中
        struct msg_st sbuf;
        struct sockaddr_in raddr;
    
        if(argc < 2)
        {
            fprintf(stderr,"Usage is short 2\n");
            exit(1);
        }
    
        sd = socket(AF_INET,SOCK_DGRAM,0);
        if(sd < 0)
        {
            perror("socket()");
            exit(1);
        }
    
    
        //bind();
        /*
            ssize_t send(int sockfd,const void *buf,size_t len,int flags);
            这个是用于流式套接字,因为式一对一通讯
            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的大小
            flags   有无特殊要求,如无设置0选择默认
            dest_addr   目的地址
            addrlen 的地址的大小
            返回值
            成功  送出去的字符个数
            失败 -1
        */
    
        //填充sbuf要发送的数据
        strcpy(sbuf.name,"Alan");
        sbuf.math = htonl(rand()%100);
        sbuf.chinese = htonl(rand()%100);
    
        //设置远端的地址,分别设置协议族、端口、IP地址
        raddr.sin_family = AF_INET;
        raddr.sin_port = htons(atoi(RCVPORT));
        inet_pton(AF_INET,argv[1],&raddr.sin_addr);
    
        if(sendto(sd,&sbuf,sizeof(sbuf),0,(void *)&raddr,sizeof(raddr)) < 0)
        {
            perror("sento()ssfd");
            exit(1);
        }
    
        puts("OK!");
    
        close(sd);
    
        exit(0);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    编译运行结果如下:
    1657709179287
    使snder与rcver建立通信,先执行./rcver,再执行./snder,执行结果如下:
    编译运行结果如下:
    1657709760180

  • 相关阅读:
    垃圾收集算法
    关于2023年下半年计算机技术与软件专业技术资格(水平)考试报名工作有关事项的通知
    阶乘(Python)
    行业“卷不动”、市场“换不动”,家电赛道又跑回“老路”
    粒子群算法求解0-1背包问题
    java发送http请求get/post
    Vulnhub | DC: 4 |【实战】
    Android 腾讯位置服务地图简单使用
    算法通关村——不简单的字符串转换问题
    VSCODE中使用Vue3教程
  • 原文地址:https://blog.csdn.net/colortztzztzt/article/details/133179967