4

私はtcpソケットを使用して、WindowsXP上の2つのアプリ間のプロセス間通信を提供しています。私はさまざまな理由でtcpソケットを選びました。平均往復時間は2.8ミリ秒です。それは私が予想していたよりもはるかに遅いです。プロファイリングは、一方のアプリがsendを呼び出してから、もう一方のアプリがブロックしているrecvが戻るまでの間に遅延があることを示しているようです。

アプリ、デーモン、クライアントもあります。これらは、次の擬似コードのように構成されています。

デーモンスレッド1(新しい接続をリッスンします):

while (1) {
   SOCKET listener_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   bind(listener_socket, (SOCKADDR*)&server_info, sizeof(SOCKADDR));
   listen(listener_socket, 1);
   SOCKET client_socket = accept(listener_socket, NULL, NULL);
   closesocket(listener_socket);
   CreateThread(client_thread);
 }

デーモンclient_socketスレッド(クライアントからのパケットをリッスンします):

char cmdBuf[256];
int cmdBufAmountData = 0;

while (1)
{   
    char recvBuf[128];
    int bytesTransferred = recv(m_clientSocket, recvBuf, sizeof(recvBuf), 0);

    // Copy received data into our accumulated command buffer (commands 
    // may be split across packet boundaries)
    memcpy(cmdBuf + cmdBufAmountData, recvBuf, bytesTransferred);
    cmdBufAmountData += bytesTransferred;

    // See if there is one or more complete commands in cmdBuf 
    // (commands are separated by '\0')
    while (commandExists(cmdBuf, cmdBufAmountData))
    {
        // do stuff with command
        send(m_clientSocket, outBuf, msgLen, 0);

        // Throw away the command we just processed by shuffling 
        // the contents of the command buffer left
        for (int i = 0; i < cmdBufAmountData - cmdLen; i++)
            cmdBuf[i] = cmdBuf[i + cmdLen];
        cmdBufAmountData -= cmdLen;
    }
}

クライアントスレッド1:

start_timer();
send(foo);
recv(barBuf);
end_timer();       // Timer shows values from 0.7ms to 17ms. Average 2.8ms.

レイテンシーがとても悪い理由はありますか?Nagelのアルゴリズムを疑ったが、コードに次のようなものを散らかした。

BOOL bOptVal = TRUE;
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&bOptVal, sizeof(BOOL));

助けにはならない。クライアントソケットとデーモンソケットの両方でこれを行う必要がありますか(私はやっています)?

私はクアッドコアマシンを使用しており、負荷やディスクアクティビティなどはほとんどありません。

4

2 に答える 2

2

まず、サーバーでは、whileループはリッスンではなくAcceptの周りにある必要があります...リッスンする必要があるのは1回だけなので、...

SOCKET listener_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(listener_socket, (SOCKADDR*)&server_info, sizeof(SOCKADDR));
listen(listener_socket, 1);
while (1) {
   SOCKET client_socket = accept(listener_socket, NULL, NULL);
   closesocket(listener_socket);
   CreateThread(client_thread);
 }

次に、はい、nagleをオフにする場合は、受け入れられたサーバーソケットと接続されたクライアントソケットの両方でオフにする必要があります。接続/承認した直後に実行できます。したがって、1つのソケットにnagleを設定するだけの場合は、それが問題になる可能性があります。

TCPを使用していることを考えると、完全なメッセージが得られるまで読んでいると想定し、一方が一方の側で送信する==もう一方の側で1つの受信が行われるとは想定していません。(つまり、コードが省略されており、通常のrecvループが表示されていないと思います)。

クライアントは何人ですか?スレッドはいくつですか?

于 2010-10-12T16:45:09.167 に答える
1

また、サーバーを終了するまで、リスニングソケットを閉じないでください。

Windows APIに縛られてもかまわないのであれば、ソケットではなく名前付きパイプを見てみましょう。

于 2010-10-13T00:43:04.140 に答える