クライアントとサーバーにブロッキング TCP ソケットを使用しています。読むときはいつでも、最初に を使用してストリーム上でデータが利用可能かどうかを確認しますselect
。私はいつも一度に 40 バイトを読み書きします。ほとんどの読み取りには数ミリ秒以下かかりますが、0.5 秒以上かかるものもあります。それは、ソケットで利用可能なデータがあることを知った後です。
私も使っていますTCP_NODELAY
何が原因ですか?
編集2
送受信された各パケットのタイムスタンプを分析したところ、この遅延は、サーバーによって次のオブジェクトが書き込まれる前にクライアントがオブジェクトを読み取ろうとした場合にのみ発生することがわかりました。たとえば、サーバーがオブジェクト番号 x を書き込んだ後、サーバーがオブジェクト番号 x+1 の書き込みを開始する前に、クライアントがオブジェクト x を読み取ろうとしました。これにより、サーバー側で何らかの合体が行われているのではないかと思われます。
編集
サーバーは 3 つの異なるポートでリッスンしています。クライアントは、これらの各ポートに 1 つずつ接続します。
3 つの接続があります。サーバーからクライアントにデータを頻繁に送信する接続です。クライアントからサーバーにデータを送信するだけの 2 つ目。そして、1バイトのデータを送信するためにめったに使用されない3番目のもの。最初の接続で問題に直面しています。その接続でデータが利用可能であることを確認しselect()
てから、40 バイトの読み取りにタイムスタンプを付けると、その読み取りに約 0.5 秒かかったことがわかります。
これをプロファイリングする方法についての指針は非常に役立ちます
Linuxでgccを使用しています。
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);
}