Sto usando blocchi TCP per il mio client e server. Ogni volta che leggo, per prima cosa controlla se i dati sono disponibili sullo streaming utilizzando select
. Leggo sempre e scrivo 40 byte alla volta. Mentre la maggior parte delle letture richiede pochi millisecondi o meno, alcuni richiedono solo più di mezzo secondo. Che dopo so che ci sono dati disponibili sul socket.Quale potrebbe essere la causa delle letture dei socket molto lente?
Sono anche utilizzando TCP_NODELAY
Quale potrebbe essere la causa?
EDIT 2
ho analizzato il timestamp per ogni pacchetto inviato e ricevuto e ho visto che questo ritardo si verifica solo quando client tenta di leggere l'oggetto prima che l'oggetto successivo viene scritto dal server. Ad esempio, il server ha scritto il numero dell'oggetto x e successivamente il client ha provato a leggere l'oggetto x, prima che il server fosse in grado di iniziare a scrivere il numero dell'oggetto x + 1. Questo mi fa sospettare che si stia verificando una sorta di coalescenza sul lato server.
EDIT
Il server è in ascolto su 3 porte diverse. Il client si collega uno per uno a ciascuna di queste porte.
Esistono tre connessioni: una che invia alcuni dati frequentemente dal server al client. Un secondo che invia solo dati dal client al server. E un terzo che viene usato molto raramente per inviare un singolo byte di dati. Sto affrontando il problema con la prima connessione. Sto verificando usando select()
che i dati sono disponibili su quella connessione e quindi quando ho il timestamp del 40 byte letto, trovo che è stato preso circa mezzo secondo per quella lettura.
Eventuali indicazioni su come al profilo questo sarebbe molto utile
utilizzando gcc su linux.
connessioni
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); }
ho avuto la sensazione che questo problema è legato all'hardware ... – Jah
** Uno che invia alcuni dati frequentemente dal server al client **, quali dimensioni siamo parlare di? – tuxuday
Forse TCP_NODELAY (disabilitazione Nagle) è una scelta sbagliata, con conseguente invio di molti segmenti brevi, con conseguente più round trip per pacchetto "logico". Inoltre un sacco di systemcall sul lato del programma applicativo. – wildplasser