Ich verwende blockierende TCP-Sockets für meinen Client und Server. Immer wenn ich lese, überprüfe ich zuerst, ob Daten im Stream verfügbar sind, indem Sie select
verwenden. Ich lese und schreibe immer 40 Bytes gleichzeitig. Während die meisten Lesevorgänge nur wenige Millisekunden oder weniger dauern, benötigen einige nur mehr als eine halbe Sekunde. Das nachdem ich weiß, dass auf dem Socket Daten vorhanden sind.Was könnte die Ursache für sehr langsame Socket Reads sein?
Ich verwende auch TCP_NODELAY
Was es verursachen könnte?
EDIT 2
analysiert I den Zeitstempel für jedes Paket gesendet und empfangen und sah, dass diese Verzögerung geschieht nur, wenn der Client das Objekt zu lesen versucht, bevor das nächste Objekt durch den Server geschrieben wird. Zum Beispiel schrieb der Server die Objektnummer x und danach versuchte der Client das Objekt x zu lesen, bevor der Server mit dem Schreiben der Objektnummer x + 1 beginnen konnte. Dies lässt mich vermuten, dass auf der Serverseite eine Art Verschmelzung stattfindet.
EDIT
Der Server, auf 3 verschiedenen Ports überwacht. Der Client verbindet sich nacheinander mit jedem dieser Ports.
Es gibt drei Verbindungen: Eine, die einige Daten häufig vom Server an den Client sendet. Ein zweiter, der nur Daten vom Client an den Server sendet. Und eine dritte, die sehr selten verwendet wird, um einzelne Datenbytes zu senden. Ich stehe vor dem Problem mit der ersten Verbindung. Ich überprüfe unter Verwendung select()
, dass Daten auf dieser Verbindung verfügbar sind, und wenn ich dann das 40-Byte-Lesen Zeitstempel, finde ich, dass ungefähr eine halbe Sekunde für diesen Lesevorgang genommen wurde.
Alle Hinweise, wie diese zum Profil auf Linux wäre
mit gcc sehr hilfreich.
rdrr_server_start(void) {
int rr_sd; int input_sd; int ack_sd; int fp_sd;
startTcpServer(&rr_sd, remote_rr_port); startTcpServer(&input_sd, remote_input_port); startTcpServer(&ack_sd, remote_ack_port); startTcpServer(&fp_sd, remote_fp_port);
connFD_rr = getTcpConnection(rr_sd); connFD_input = getTcpConnection(input_sd); connFD_ack= getTcpConnection(ack_sd); connFD_fp=getTcpConnection(fp_sd); }
static int getTcpConnection(int sd) { socklen_t l en;
struct sockaddr_in clientAddress; len = sizeof(clientAddress); int connFD = accept(sd, (struct sockaddr*) &clientAddress, &len); nodelay(connFD); fflush(stdout); return connFD; }
static void startTcpServer(int *sd, const int port) { *sd= socket(AF_INET, SOCK_STREAM, 0); ASSERT(*sd>0);
// Set socket option so that port can be reused int enable = 1; setsockopt(*sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
struct sockaddr_in a; memset(&a,0,sizeof(a)); a.sin_family = AF_INET; a.sin_port = port; a.sin_addr.s_addr = INADDR_ANY; int bindResult = bind(*sd, (struct sockaddr *) &a, sizeof(a)); ASSERT(bindResult ==0); listen(*sd,2); } static void nodelay(int fd) { int flag=1; ASSERT(setsockopt(fd, SOL_TCP, TCP_NODELAY, &flag, sizeof flag)==0); }
startTcpClient() { connFD_rr = socket(AF_INET, SOCK_STREAM, 0); connFD_input = socket(AF_INET, SOCK_STREAM, 0); connFD_ack = socket(AF_INET, SOCK_STREAM, 0); connFD_fp= socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in a; memset(&a,0,sizeof(a)); a.sin_family = AF_INET; a.sin_port = remote_rr_port; a.sin_addr.s_addr = inet_addr(remote_server_ip);
int CONNECT_TO_SERVER= connect(connFD_rr, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_input_port; CONNECT_TO_SERVER= connect(connFD_input, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_ack_port; CONNECT_TO_SERVER= connect(connFD_ack, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
a.sin_port = remote_fp_port; CONNECT_TO_SERVER= connect(connFD_fp, &a, sizeof(a)); ASSERT(CONNECT_TO_SERVER==0) ;
nodelay(connFD_rr); nodelay(connFD_input); nodelay(connFD_ack); nodelay(connFD_fp); }
bewegen bekam ich das Gefühl, dass dieses Problem ist Hardware im Zusammenhang ... – Jah
** Eines, das einige Daten häufig von dem Server an den Client sendet **, welche Größe wir sind sprechen über? – tuxuday
Vielleicht ist TCP_NODELAY (Deaktivieren von Nagle) eine schlechte Wahl, was dazu führt, dass viele kurze Segmente gesendet werden, was zu mehreren Round-Trips pro "logischem" Paket führt. Außerdem viele Systemanrufe an der Seite des Anwendungsprogramms. – wildplasser