【发布时间】:2012-02-22 22:20:28
【问题描述】:
我曾经认为write()系统调用是无缓冲的,fwrite和fread用于缓冲IO。但是,我编写了简单的程序来确定在使用write() 时某些缓冲仍在进行。我在套接字上使用write() 和read()。由于缓冲,客户端可能会在服务器不断发送数据包时滞后。我不要那个。我希望客户端必须在服务器发送更多记录之前使用记录。
如何在不增加确认等网络负载的情况下实现这一点!
我在 linux 上使用 gcc
server.c:
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/tcp.h>
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 <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/tcp.h>
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;
}
【问题讨论】:
-
你使用什么协议? TCP 自己管理数据流,在这种情况下,您将不得不忍受它。这不仅仅是一个本地磁盘,在你和目的地之间有很多排队代码。如果您不关心确认,您可以只触发一个 UDP 数据包并继续下一条记录,但不知道收件人是否真的得到了记录。
-
您认为
write(2)没有缓冲是正确的。 Nagle 算法是 TCP 的一部分!