Używam blokowania gniazd TCP dla mojego klienta i serwera. Zawsze, gdy czytam, najpierw sprawdzam, czy dane są dostępne w strumieniu za pomocą select
. Zawsze czytam i zapisuję 40 bajtów na raz. Podczas gdy większość czytań zajmuje kilka milisekund lub mniej, niektóre z nich zajmują więcej niż pół sekundy. Po tym, jak wiem, że są dostępne dane na gnieździe.Co może być przyczyną bardzo wolnego odczytywania gniazd?
Jestem również za pomocą TCP_NODELAY
Co może być przyczyną tego?
EDIT 2
analizowałem znacznika czasu dla każdego pakietu wysłanych i odebranych i zobaczył, że opóźnienie to się dzieje tylko wtedy, gdy klient próbuje odczytać przedmiot przed następnym celem jest zapisywany przez serwer. Na przykład, serwer napisał obiekt numer x, a następnie klient próbował odczytać obiekt x, zanim serwer był w stanie rozpocząć pisanie obiektu numer x + 1. To sprawia, że podejrzewam, że pewnego rodzaju koalescencja ma miejsce po stronie serwera.
EDIT
Serwer nasłuchuje na 3 różnych portów. Klient łączy się kolejno z każdym z tych portów.
Istnieją trzy połączenia: Jedna, która wysyła częste dane z serwera do klienta. Drugi, który wysyła dane tylko od klienta do serwera. Trzeci, który jest bardzo rzadko używany do przesyłania pojedynczego bajtu danych. Mam problem z pierwszym połączeniem. Sprawdzam przy użyciu select()
, że dane są dostępne dla tego połączenia, a następnie, gdy znacznik czasu odczytuje 40 bajtów, stwierdzam, że około pół sekundy zostało zrobione dla tego odczytu.
Wszelkie wskazówki co do sposobu profilu To byłoby bardzo pomocne
używając gcc na linux.
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); }
Mam wrażenie, że ten problem jest związany ze sprzętem ... – Jah
** Jeden, który wysyła jakieś dane często z serwera do klienta **, jaki rozmiar jesteśmy rozmawiać o? – tuxuday
Być może TCP_NODELAY (wyłączenie Nagle) jest złym wyborem, w wyniku czego wysyłanych jest wiele krótkich segmentów, co powoduje wielokrotne podróże w obie strony na "logiczny" pakiet. Plus wiele systemów po stronie aplikacji. – wildplasser