259 Stimmen

Was ist der Unterschied zwischen read() und recv(), und zwischen send() und write()?

Was ist der Unterschied zwischen read() y recv() und zwischen send() y write() in der Socket-Programmierung in Bezug auf Leistung, Geschwindigkeit und andere Verhaltensweisen?

5voto

Rick Punkte 5919

Unter Linux stelle ich außerdem fest, dass :

Unterbrechung von Systemaufrufen und Bibliotheksfunktionen durch Signalhandler
Wenn ein Signalhandler aufgerufen wird, während ein Systemaufruf oder ein Bibliotheksfunktionsaufruf blockiert ist, dann wird entweder:

  • der Aufruf wird automatisch neu gestartet, nachdem der Signalhandler zurückgekehrt ist; oder

  • scheitert der Aufruf mit dem Fehler EINTR.

... Die Details variieren von UNIX-System zu UNIX-System; im Folgenden werden die Details für Linux beschrieben.

Wenn ein blockierter Anruf an eine der folgenden Stellen durch einen Signalhandler unterbrochen wird, dann wird der Aufruf autom der Signalhandler zurückkehrt, wenn das Flag SA_RESTART verwendet wurde; andernfalls schlägt der Aufruf mit dem Fehler EINTR fehl:

  • lesen (2), readv(2), write(2), writev(2) und ioctl(2) Aufrufe auf "langsamen" Geräten.

.....

Die folgenden Schnittstellen werden nie neu gestartet, nachdem sie von einem Signalhandler unterbrochen wurden, unabhängig von der Verwendung von SA_RESTART; sie scheitern immer mit dem Fehler EINTR, wenn sie durch einen Signalhandler unterbrochen werden:

  • "Input"-Socket-Schnittstellen, wenn ein Timeout (SO_RCVTIMEO) auf dem Socket mit setsockopt(2) gesetzt wurde: accept(2), recv ( Abruf von (2), recvmmsg(2) (auch mit einem Nicht-NULL-Timeout-Argument) und recvmsg(2).

  • "Output"-Socket-Schnittstellen, wenn ein Timeout (SO_RCVTIMEO) auf dem Socket mit setsockopt(2) gesetzt wurde: connect(2), send(2), sendto(2), und sendmsg(2).

Siehe man 7 signal für weitere Einzelheiten.


Eine einfache Anwendung wäre die Verwendung von Signal zur Vermeidung von recvfrom Sperrung auf unbestimmte Zeit.

Ein Beispiel aus APUE :

#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);
}

3voto

unwind Punkte 377331

"Leistung und Geschwindigkeit"? Sind das nicht so etwas wie ... Synonyme, hier?

Wie auch immer, die recv() Aufruf nimmt Flaggen, die read() nicht, was es leistungsfähiger oder zumindest bequemer macht. Das ist ein Unterschied. Ich glaube nicht, dass es einen signifikanten Leistungsunterschied gibt, habe es aber nicht getestet.

1voto

Der einzige Unterschied zwischen recv() und read() ist das Vorhandensein von Flags. Mit einem Argument ohne Flags ist recv() im Allgemeinen gleichwertig mit read()

0voto

Sie können write() und read() anstelle von send() und recv() verwenden, aber send() und recv() bieten eine viel bessere Kontrolle über Ihre Datenübertragung

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X