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?
Antworten
Zu viele Anzeigen?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);
}
"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.
- See previous answers
- Weitere Antworten anzeigen