代码之家  ›  专栏  ›  技术社区  ›  gt124

read()和recv()之间以及send()和write()之间有什么区别?

  •  166
  • gt124  · 技术社区  · 7 年前

    read() recv() send() write() 在socket编程中,性能、速度和其他行为如何?

    6 回复  |  直到 6 年前
        1
  •  148
  •   smbear    7 年前

    区别在于 recv() / send() SIGPIPE ,或发送带外消息。

    read() / write() 是吗

        2
  •  93
  •   Jonathan Feinberg    16 年前

    the first hit on Google

    read()相当于recv(),flags参数为0。flags参数的其他值会更改recv()的行为。类似地,write()相当于send(),其标志=0。

        3
  •  15
  •   Bastien Léonard    16 年前

    read() write() 它们更通用,可用于任何文件描述符。 但是,它们不能在Windows上工作。

    您可以将其他选项传递给 send() recv() ,因此在某些情况下您可能不得不使用它们。

        4
  •  7
  •   kj.    10 年前

    我最近注意到当我使用 write() 在Windows中的套接字上,它几乎可以工作(FD传递给 写() 和传给你的不一样吗 send() ; 我曾经 _open_osfhandle() 让FD传递给 ).但是,当我试图发送包含字符10的二进制数据时,它不起作用。 在此之前插入字符13。改成 发送() 使用flags参数0修复了该问题。 read() 如果13-10在二进制数据中是连续的,可能会出现相反的问题,但我还没有测试它。但这似乎是两者之间的另一个可能区别 写()

        5
  •  6
  •   Mert Mertce    10 年前

    linux上的另一件事是:

    send 不允许在非插座fd上操作。因此,例如在usb端口上写入, write

        6
  •  2
  •   unwind    16 年前

    “性能和速度”?那不是那种。。。同义词,这里?

    不管怎样 recv() read() 没有,这使得它更强大,或者至少更方便。这是一个区别。我不认为有显著的性能差异,但还没有测试过。

        7
  •  2
  •   Rick    6 年前

    在Linux上,我还注意到:

    信号处理程序中断系统调用和库函数
    如果在系统调用或库函数调用被阻止时调用信号处理程序,则:

    • 调用失败,错误为EINTR。

    如果对以下接口之一的阻塞调用被中断 如果使用了SA_重新启动标志,则信号处理程序返回;否则调用将失败,错误为EINTR:

    • 阅读

    .....

    当被信号处理程序中断时,始终失败并出现错误EINTR:

    • 记录 接收数据

    • “输出”套接字接口,当使用setsockopt(2)在套接字上设置超时(SO_RCVTIMEO)时:连接(2),发送(2),

    检查 man 7 signal 更多细节。


    一个简单的用法是使用信号来避免 recvfrom

    来自 阿普 :

    #include "apue.h"
    #include <netdb.h>
    #include <errno.h>
    #include <sys/socket.h>
    
    #define BUFLEN      128
    #define TIMEOUT     20
    
    void
    sigalrm(int signo)
    {
    }
    
    void
    print_uptime(int sockfd, struct addrinfo *aip)
    {
        int     n;
        char    buf[BUFLEN];
    
        buf[0] = 0;
        if (sendto(sockfd, buf, 1, 0, aip->ai_addr, aip->ai_addrlen) < 0)
            err_sys("sendto error");
        alarm(TIMEOUT);
        //here
        if ((n = recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL)) < 0) {
            if (errno != EINTR)
                alarm(0);
            err_sys("recv error");
        }
        alarm(0);
        write(STDOUT_FILENO, buf, n);
    }
    
    int
    main(int argc, char *argv[])
    {
        struct addrinfo     *ailist, *aip;
        struct addrinfo     hint;
        int                 sockfd, err;
        struct sigaction    sa;
    
        if (argc != 2)
            err_quit("usage: ruptime hostname");
        sa.sa_handler = sigalrm;
        sa.sa_flags = 0;
        sigemptyset(&sa.sa_mask);
        if (sigaction(SIGALRM, &sa, NULL) < 0)
            err_sys("sigaction error");
        memset(&hint, 0, sizeof(hint));
        hint.ai_socktype = SOCK_DGRAM;
        hint.ai_canonname = NULL;
        hint.ai_addr = NULL;
        hint.ai_next = NULL;
        if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)
            err_quit("getaddrinfo error: %s", gai_strerror(err));
    
        for (aip = ailist; aip != NULL; aip = aip->ai_next) {
            if ((sockfd = socket(aip->ai_family, SOCK_DGRAM, 0)) < 0) {
                err = errno;
            } else {
                print_uptime(sockfd, aip);
                exit(0);
            }
        }
    
        fprintf(stderr, "can't contact %s: %s\n", argv[1], strerror(err));
        exit(1);
    }