• recv用TCP和TUDP下的区别


    recv是可以用在UDP套接字上的,前提是该套接字调用过bind或者connect,那它用在TCP和UDP套接字上时有什么区别呢?

    下面做一个测试,分别使用UDP、TCP实现一对C/S、客户端发送12字节数据,服务器接受的时候用10字节大小的buffer去接受。

    TCP

    tcpSvr:

     1 /*
     2  * gcc -o tcpSvr ./tcpSvr.c
     3  */
     4 #include <unistd.h>
     5 #include <sys/socket.h>
     6 #include <sys/types.h>
     7 #include <arpa/inet.h>
     8 #include <netinet/in.h>
     9 #include <stdio.h>
    10 #include <string.h>
    11 #include <errno.h>
    12 
    13 const int PORT = 8080;
    14 
    15 int main(int argc, char **argv)
    16 {
    17     int fd = socket(AF_INET, SOCK_STREAM, 0);
    18     if (fd == -1)
    19     {
    20         perror("socket");
    21         return errno;
    22     }
    23 
    24     struct sockaddr_in addr;
    25     memset(&addr, 0, sizeof(addr));
    26     addr.sin_family = AF_INET;
    27     addr.sin_addr.s_addr = INADDR_ANY;
    28     addr.sin_port = htons(PORT);
    29 
    30     if (-1 == bind(fd, (struct sockaddr*)&addr, sizeof(addr)))
    31     {
    32         perror("bind");
    33         return errno;
    34     }
    35 
    36     if (-1 == listen(fd, 5))
    37     {
    38         perror("listen");
    39         return errno;
    40     }
    41 
    42     struct sockaddr_in cli_addr;
    43     socklen_t len = sizeof(cli_addr);
    44     int client = accept(fd, (struct sockaddr*)&cli_addr, &len);
    45     if (client == -1)
    46     {
    47         perror("accept");
    48         return errno;
    49     }
    50     
    51     printf("accept an client
    ");
    52 
    53     char buf[1024];
    54     while(1)
    55     {
    56         memset(buf, 0, 1024);
    57         int iRet = recv(client, buf, 10, 0);
    58         printf("recv data len [%d]
    ", iRet);
    59         printf("recv content [%s]
    ", buf);
    60         sleep(2);
    61     }
    62     close(fd);
    63 
    64     return 0;
    65 }

    tcpCli:

     1 #include <unistd.h>
     2 #include <sys/socket.h>
     3 #include <sys/types.h>
     4 #include <netinet/in.h>
     5 #include <arpa/inet.h>
     6 #include <stdio.h>
     7 #include <string.h>
     8 #include <errno.h>
     9 
    10 const int PORT = 8080;
    11 
    12 int main(int argc, char **argv)
    13 {
    14     int fd = socket(AF_INET, SOCK_STREAM, 0);
    15     if (fd == -1)
    16     {
    17         perror("socket");
    18         return errno;
    19     }
    20 
    21     struct sockaddr_in addr;
    22     memset(&addr, 0, sizeof(addr));
    23     addr.sin_family = AF_INET;
    24     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    25     addr.sin_port = htons(PORT);
    26 
    27     if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
    28     {
    29         perror("connect");
    30         return errno;
    31     }
    32 
    33     char buf[] = "hello world!";
    34     while (1)
    35     {
    36         int iRet = send(fd, buf, strlen(buf), 0); 
    37         printf("Send data len [%d]
    ", iRet);
    38         printf("Send content [%s]
    ", buf);
    39         sleep(2);
    40     }
    41     close(fd);
    42 
    43     return 0;
    44 }

    结果:

    UDP

    udpSvr

     1 #include <unistd.h>
     2 #include <sys/socket.h>
     3 #include <sys/types.h>
     4 #include <arpa/inet.h>
     5 #include <netinet/in.h>
     6 #include <stdio.h>
     7 #include <string.h>
     8 #include <errno.h>
     9 
    10 const int PORT = 8080;
    11 
    12 int main(int argc, char **argv)
    13 {
    14     int fd = socket(AF_INET, SOCK_DGRAM, 0);
    15     if (fd == -1)
    16     {
    17         perror("socket");
    18         return errno;
    19     }
    20 
    21     struct sockaddr_in addr;
    22     memset(&addr, 0, sizeof(addr));
    23     addr.sin_family = AF_INET;
    24     addr.sin_addr.s_addr = INADDR_ANY;
    25     addr.sin_port = htons(PORT);
    26 
    27     if (-1 == bind(fd, (struct sockaddr*)&addr, sizeof(addr)))
    28     {
    29         perror("bind");
    30         return errno;
    31     }
    32 
    33     char buf[1024];
    34     while(1)
    35     {
    36         memset(buf, 0, 1024);
    37         int iRet = recv(fd, buf, 10, 0);
    38         printf("recv data len [%d]
    ", iRet);
    39         printf("recv content [%s]
    ", buf);
    40     }
    41     close(fd);
    42 
    43     return 0;
    44 }

    udpCli:

     1 #include <unistd.h>
     2 #include <sys/socket.h>
     3 #include <sys/types.h>
     4 #include <netinet/in.h>
     5 #include <arpa/inet.h>
     6 #include <stdio.h>
     7 #include <string.h>
     8 #include <errno.h>
     9 
    10 const int PORT = 8080;
    11 
    12 int main(int argc, char **argv)
    13 {
    14     int fd = socket(AF_INET, SOCK_DGRAM, 0);
    15     if (fd == -1)
    16     {
    17         perror("socket");
    18         return errno;
    19     }
    20 
    21     struct sockaddr_in addr;
    22     memset(&addr, 0, sizeof(addr));
    23     addr.sin_family = AF_INET;
    24     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    25     addr.sin_port = htons(PORT);
    26 
    27     char buf[] = "hello world!";
    28     while (1)
    29     {
    30         int iRet = sendto(fd, buf, strlen(buf), 0, (struct sockaddr*)&addr, sizeof(addr));
    31         printf("Send data len [%d]
    ", iRet);
    32         printf("Send content [%s]
    ", buf);
    33         break;
    34     }
    35     close(fd);
    36 
    37     return 0;
    38 }

    结果:

    结论:

    当收到的数据大于传入recv的buffer大小时,多余的字节,UDP会丢弃,TCP可以在下次调用recv的时候读取到,这也是为什么说TCP是基于流的协议。

    所以当读取UDP数据时一定要注意buffer的大小,应使它大于IP层的数据报大小。

    还需要注意的是,发送UDP数据的时候包的大小不应该导致IP分片,否则会造成乱序、丢包。

  • 相关阅读:
    (译).NET4.X并行任务Task需要释放吗?
    微软面向高并发应用而推出的新程序库——TPL Dataflow
    C# 5.0 Async函数的提示和技巧
    内存泄露——文章
    AJAX POST请求中参数以form data和request payload形式在php中的获取方式
    NodeJS中间层搭建
    HTML5上传预览
    laravel 图片上传 ajax 方式
    抽奖程序
    IText 生成页脚页码
  • 原文地址:https://www.cnblogs.com/lit10050528/p/6283827.html
Copyright © 2020-2023  润新知