J’avais l’habitude de penser que l’appel système write()
n’est pas mis en mémoire tampon et que fwrite
et fread
sont utilisés pour les entrées-sorties en mémoire tampon. Cependant, j’ai écrit des programmes simples pour établir qu’il restait de la mémoire tampon lors de l’utilisation de write()
. J’utilise write()
et read()
sur des sockets. En raison de la mise en mémoire tampon, il est possible que le client soit à la traîne pendant que le serveur continue à envoyer des paquets. Je ne veux pas ça. Je veux que le client doit consumr l’enregistrement avant que le serveur envoie plus d’enregistrements.
Comment puis-je y arriver sans append une charge réseau d’accusés de réception, etc.!
J’utilise gcc sur linux
server.c:
#include #include #include #include #include #include #include #include #include #include #include int remote_rr_port=2000; // Server will send RR logs using connection on this port. char const *remote_server_ip="127.0.0.1"; int connFD_rr; static void startTcpServer(int *sd, const int port) { *sd= socket(AF_INET, SOCK_STREAM, 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)); listen(*sd,2); } // Wait for connection from client static int getTcpConnection(int sd) { char buf[100]; socklen_t len; struct sockaddr_in clientAddress; printf("\nWaiting for connection from remote client\n"); len = sizeof(clientAddress); int connFD = accept(sd, (struct sockaddr*) &clientAddress, &len); setsockopt(connFD_rr, SOL_SOCKET, SO_SNDBUF, (int[]){0}, sizeof(int)); printf("\n Connection from : %s:%d\n",inet_ntop(AF_INET, &clientAddress.sin_addr, buf, sizeof(buf)),clientAddress.sin_port); fflush(stdout); return connFD; } FILE* rdrr_server_start(void) { // Socket Descriptors for the two connections int rr_sd; int input_sd; startTcpServer(&rr_sd, remote_rr_port); connFD_rr = getTcpConnection(rr_sd); return fdopen(connFD_rr, "w"); } int main() { int i = 0; rdrr_server_start(); for(i=0;i<10000000; i++) { write(connFD_rr, &i, sizeof (int)); printf("%d\n", i); } return 0; }
client.c:
#include #include #include #include #include #include #include #include #include int remote_rr_port=2000; // Server will send RR logs using connection on this port. char const *remote_server_ip="127.0.0.1"; int connFD_rr; FILE* rdrr_client_start(void) { connFD_rr = 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); printf("\nConnecting to Server on RR port"); int CONNECT_TO_SERVER= connect(connFD_rr,(struct sockaddr *) &a, sizeof(a)); printf("\nConnected to server on RR port"); setsockopt(connFD_rr, SOL_SOCKET, SO_RCVBUF, (int[]){0}, sizeof(int)); return fdopen(connFD_rr, "r"); } int main() { int i = 0; rdrr_client_start(); getrchar(); while(1) { read(connFD_rr, &i, sizeof (int)); printf("%d\n", i); } return 0; }
Peut-être que ce que vous voulez dire, c’est que vous voulez désactiver l’algorithme de Nagle, auquel cas la solution est:
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (int[]){1}, sizeof(int));
Edit: Hum, on dirait que vous voulez plus que cela, et je doute que ce que vous voulez soit possible sans concevoir votre propre protocole sur UDP.
Edit 2: Vous pourrez peut-être obtenir un effet similaire à ce que vous voulez en limitant la taille des tampons d’envoi et de réception. Le serveur (expéditeur) doit faire:
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (int[]){YOUR_BUF_LIMIT}, sizeof(int));
et le client (destinataire) doit faire:
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (int[]){YOUR_BUF_LIMIT}, sizeof(int));