• UDP协议 sendto 和 recvfrom 浅析与示例


      UDP(user datagram protocol)用户数据报协议,属于传输层。

      UDP是面向非连接的协议,它不与对方建立连接,而是直接把数据报发给对方。UDP无需建立类如三次握手的连接,使得通信效率很高。因此UDP适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。

    UDP示意图

      UDP通信的过程如图所示:

        服务端:

          (1)使用函数socket(),生成套接字文件描述符;

          (2)通过struct sockaddr_in 结构设置服务器地址和监听端口;

          (3)使用bind() 函数绑定监听端口,将套接字文件描述符和地址类型变量(struct sockaddr_in )进行绑定;

          (4)接收客户端的数据,使用recvfrom() 函数接收客户端的网络数据;

          (5)向客户端发送数据,使用sendto() 函数向服务器主机发送数据;

          (6)关闭套接字,使用close() 函数释放资源;

        客户端:

          (1)使用socket(),生成套接字文件描述符;

          (2)通过struct sockaddr_in 结构设置服务器地址和监听端口;

          (3)向服务器发送数据,sendto() ;

          (4)接收服务器的数据,recvfrom() ;

          (5)关闭套接字,close() ;


      (关于 sockaddr sockaddr_in 的区别,可参考:https://blog.csdn.net/qingzhuyuxian/article/details/79736821

    sendto()

    1 1 int sendto(int s, const void *buf, int len, unsigned int flags, 
    2         const struct sockaddr *to, int tolen);

      返回值说明:

        成功则返回实际传送出去的字符数,失败返回-1,错误原因会存于errno 中。

      参数说明:

        s:      socket描述符;
        buf:  UDP数据报缓存区(包含待发送数据);
        len:   UDP数据报的长度;
        flags:调用方式标志位(一般设置为0);
        to:  指向接收数据的主机地址信息的结构体(sockaddr_in需类型转换);
        tolen:to所指结构体的长度;

    recvfrom()

    1 int recvfrom(int s, void *buf, int len, unsigned int flags,
    2           struct sockaddr *from, int *fromlen); 

      返回值说明:

        成功则返回实际接收到的字符数,失败返回-1,错误原因会存于errno 中。

      参数说明:

        s:          socket描述符;
        buf:       UDP数据报缓存区(包含所接收的数据); 
        len:       缓冲区长度。 
        flags:    调用操作方式(一般设置为0)。 
        from:     指向发送数据的客户端地址信息的结构体(sockaddr_in需类型转换);
        fromlen:指针,指向from结构体长度值。

    示例代码

    服务端

     1 #include <unistd.h>
     2 #include <string.h>
     3 #include <stdio.h>
     4 #include <iostream>
     5 #include <netinet/in.h>
     6 #include <sys/socket.h>
     7 #include <sys/types.h>
     8 #include <arpa/inet.h>
     9 
    10 #define MAXLINE 4096
    11 #define UDPPORT 8001
    12 #define SERVERIP "192.168.255.129"
    13 
    14 using namespace std;
    15 
    16 int main(){
    17     int serverfd;
    18     unsigned int server_addr_length, client_addr_length;
    19     char recvline[MAXLINE];
    20     char sendline[MAXLINE];
    21     struct sockaddr_in serveraddr , clientaddr;
    22 
    23     // 使用函数socket(),生成套接字文件描述符;
    24     if( (serverfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ){
    25         perror("socket() error");
    26         exit(1);
    27     }
    28 
    29     // 通过struct sockaddr_in 结构设置服务器地址和监听端口;
    30     bzero(&serveraddr,sizeof(serveraddr));
    31     serveraddr.sin_family = AF_INET;
    32     serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    33     serveraddr.sin_port = htons(UDPPORT);
    34     server_addr_length = sizeof(serveraddr);
    35 
    36     // 使用bind() 函数绑定监听端口,将套接字文件描述符和地址类型变量(struct sockaddr_in )进行绑定;
    37     if( bind(serverfd, (struct sockaddr *) &serveraddr, server_addr_length) < 0){
    38         perror("bind() error");
    39         exit(1); 
    40     }
    41     
    42     // 接收客户端的数据,使用recvfrom() 函数接收客户端的网络数据;
    43     client_addr_length = sizeof(sockaddr_in);
    44     int recv_length = 0;
    45     recv_length = recvfrom(serverfd, recvline, sizeof(recvline), 0, (struct sockaddr *) &clientaddr, &client_addr_length);
    46     cout << "recv_length = "<< recv_length <<endl;
    47     cout << recvline << endl;
    48     
    49     // 向客户端发送数据,使用sendto() 函数向服务器主机发送数据;
    50     int send_length = 0;
    51     sprintf(sendline, "hello client !");
    52     send_length = sendto(serverfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &clientaddr, client_addr_length);
    53     if( send_length < 0){
    54         perror("sendto() error");
    55         exit(1);
    56     }
    57     cout << "send_length = "<< send_length <<endl;
    58     
    59     //关闭套接字,使用close() 函数释放资源;
    60     close(serverfd);
    61 
    62     return 0;
    63 }
    View Code

    客户端

     1 #include <unistd.h>
     2 #include <string.h>
     3 #include <stdio.h>
     4 #include <iostream>
     5 #include <netinet/in.h>
     6 #include <sys/socket.h>
     7 #include <sys/types.h>
     8 #include <arpa/inet.h>
     9 
    10 #define MAXLINE 4096
    11 #define UDPPORT 8001
    12 #define SERVERIP "192.168.255.129"
    13 
    14 using namespace std;
    15 
    16 int main(){
    17     int confd;
    18     unsigned int addr_length;
    19     char recvline[MAXLINE];
    20     char sendline[MAXLINE];
    21     struct sockaddr_in serveraddr;
    22 
    23     // 使用socket(),生成套接字文件描述符;
    24     if( (confd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ){
    25         perror("socket() error");
    26         exit(1);
    27     }
    28 
    29     //通过struct sockaddr_in 结构设置服务器地址和监听端口;
    30     bzero(&serveraddr, sizeof(serveraddr));
    31     serveraddr.sin_family = AF_INET;
    32     serveraddr.sin_addr.s_addr = inet_addr(SERVERIP);
    33     serveraddr.sin_port = htons(UDPPORT);
    34     addr_length = sizeof(serveraddr);
    35 
    36     // 向服务器发送数据,sendto() ;
    37     int send_length = 0;
    38     sprintf(sendline,"hello server!");
    39     send_length = sendto(confd, sendline, sizeof(sendline), 0, (struct sockaddr *) &serveraddr, addr_length);
    40     if(send_length < 0 ){
    41         perror("sendto() error");
    42         exit(1);
    43     }
    44     cout << "send_length = " << send_length << endl;
    45 
    46     // 接收服务器的数据,recvfrom() ;
    47     int recv_length = 0;
    48     recv_length = recvfrom(confd, recvline, sizeof(recvline), 0, (struct sockaddr *) &serveraddr, &addr_length);
    49     cout << "recv_length = " << recv_length <<endl;
    50     cout << recvline << endl; 
    51 
    52     // 关闭套接字,close() ;
    53     close(confd);
    54 
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    图片懒加载
    文字表情转换成小图标
    页面跳页面的参数获取
    vue v-for里面再套v-if和v-esle
    滚动条样式的修改
    vue-cil生产环境和发布环境的配置
    css隐藏滚动条并且可以滑动
    vue-cli脚手架一些插件安装elementui和axios
    闭包
    定时器、运动、日历
  • 原文地址:https://www.cnblogs.com/HpeMephisto/p/11312193.html
Copyright © 2020-2023  润新知