0

私は最近ネットワークプログラミングに取り組んでいます、そして私はそれが正しいかどうかをチェックするために2つの簡単なルーチンを書きました。そこで、デスクトップ上にサーバーを構築して起動し、次にラップトップ上にクライアントを構築して実行したところ、すべてが期待どおりに進みました。2回目以降に実行しようとすると、サーバーはループを続け、2秒後にクライアントは「接続エラー!」を返しました。15分後に再試行すると機能しますが、それからもう一度待つ必要があります。私はどこが間違っていますか?コンピューターは両方とも私のLANに接続されています。79.13.199.165は私のモデム/ルーターのIPであり、ポート53124のすべての着信接続をデスクトップに転送します。この問題は、サーバーとクライアントの両方を同じPCで実行している場合には発生しません。

server.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int main () {
    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(53124);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));

    int mysocket = socket(PF_INET, SOCK_STREAM, 0);
    bind(mysocket, (struct sockaddr*)&sa, sizeof(sa));
    listen(mysocket, 5);

    int inc;
    struct sockaddr_in inc_addr;
    socklen_t inc_addr_size = sizeof(inc_addr);
    inc = accept(mysocket, (struct sockaddr*)&inc_addr, &inc_addr_size);
    if (inc != -1) {
            printf("accepting client\n");
    }
    send(inc, "ciao", sizeof("ciao"), 0);
    close(inc);

    return 0;
}

client.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int main () {

    struct sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(53124);
    sa.sin_addr.s_addr = inet_addr("79.13.199.165");
    memset(sa.sin_zero, '\0', sizeof(sa.sin_zero));

   int mysocket = socket(PF_INET, SOCK_STREAM, 0);
   if (mysocket == -1) {
       printf("Could not create socket!\n");
    }
   if (connect(mysocket, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
       printf("Error connecting!\n");
    }
   char message[5];
   memset(message, '\0', sizeof(message));
   recv(mysocket, message, 5, 0);
   printf("%s\n", message);

   return 0;
}
4

1 に答える 1

4

サーバーがソケットを閉じると、いくつかのACKパケットが接続を介して逆方向および順方向に送信されます。最後のACKが正常に配信されたかどうかを判断する方法がないため、接続は少しの間TIME_WAIT状態になります。これにより、基本的にTCPスタックは、失われたパケットを待機して破棄する時間を確保できます。

これを無視して、setsockopt()を使用してSO_REUSEADDRを設定することにより、すぐにソケットを再利用することができます。後続の接続で想定外のデータが取得される可能性があるという小さな危険がありますが、小さなテストアプリケーションでは問題にならないはずです。

編集

ちなみに、おそらくこれに混乱していた理由の1つは、socket()bind()またはlisten()でエラーチェックを行わないことです。bind()呼び出しは確かにエラーを返し、Linuxではerrno、EINVALを設定します。

于 2012-04-16T13:41:39.987 に答える