3

クライアントが起動し、サーバーに接続するCでTCPクライアントプログラムを作成しようとしています。次に、少しの情報を送信し、受信した内容に耳を傾け、それに応じて反応します。

私が苦労している部分は、継続的なリスニングです。これが私が持っているものです

...

while (1) {
   numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0);
   buf[numbytes] = '\0';
   printf("Received: %s\n", buf);
   // more code to react goes here
}

...

サーバーに接続すると、2行のデータを送信した後、サーバーはかなりの情報を受け取るはずですが、これを実行すると次のように出力されます。

受け取った:

そして、強制的に閉じるまで、そこに座ったままにします。

**編集**ジョナサンが私に言ったことをすると、次のようになります:

カウント: -1、エラー: 111、受信:

それはエラーを意味しますが、どうすればよいですか?

4

4 に答える 4

4

受信したバイト数を出力してください - ゼロである可能性が高いですが、それを確認してください。

エラーが発生していないこと、つまりバッファがアンダーフローしていないことを確認する価値があります。

[注: ここから先は Pax の仕事です -ありがとうございます。これを Community Wiki に変換したので、不当に担当者ポイントを取得することはありません。]

次のコードはこれを行います。試してみて、結果を報告してください。

while (1) {
    numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0);
    buf[numbytes] = '\0';
    printf("Count: %d, Error: %d, Received: %s\n", numbytes, errno, buf);
    // more code to react goes here
}

質問の編集後:

エラー番号 111 は ECONNREFUSED です。これは通常の recv() のエラー コードではありませんが、オープン タイプの呼び出し (open()、connect() など) により適しています。

いずれにせよ、ECONNREFUSED はクライアントではなくサーバー側の問題です。サーバーは意図的に着信接続の受け入れを拒否しているため、リンクのその側を調査する必要があります。

これをテストするには、ポート 80 で www.microsoft.com に接続するようにコードを変更してから、古いゴミを数行送信します。Web サーバーから、不正な形式の HTTP 要求を示すエラーが返されるはずです。これにより、クライアント側に問題がないことが証明されます。

これはtelnet www.microsoft.com 80、入力してから2回入力すると、helloENTERのように返されます。

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 27 Nov 2008 01:45:09 GMT
Connection: close
Content-Length: 326

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Verb</h2>
<hr><p>HTTP Error 400. The request verb is invalid.</p>
</BODY></HTML>

似たようなものが表示されるはずです。

于 2008-11-26T02:26:47.493 に答える
2

Beejのネットワークプログラミングガイドを強くお勧めします。

特にこのセクションには、あなたが求めることを正確に実行するクライアント用のコードがあります。

于 2008-11-26T02:43:55.340 に答える
0

無限ループとは何ですか?読み取る実際のデータがある場合にのみrecv()を呼び出すように、select()を使用してみませんか?

以前の生活では、MUDのネットワークコードを作成しましたが、それでもポーリングループを頭の中で作成できます。ROM 2.3のループは次のようになりました(メモリからなので、マクロパラメータの順序が間違っている場合はご容赦ください)。

#define MAX_CONNECTIONS 256
int main(int argc, char *argv[])
{
  int i = 0;
  int running = 1;
  int connections[MAX_CONNECTIONS];
  while( running )
  {
    fd_set in_fd, out_fd, exc_fd;
    FD_ZERO(in_fd);
    FD_ZERO(out_fd);
    FD_ZERO(exc_fd);
    for( i = 0; i < MAX_CONNECTIONS; i++ )
    {
      if( connections[i] > 0 )
      {
        FD_SET(&in_fd, connections[i]);
        FD_SET(&out_fd, connections[i]);
        FD_SET(&exc_fd, connections[i]);
      }
    }
    select(&in_fd, &out_fd, &exc_fd, NULL); // this will block until there's an I/O to handle.
    for( i = 0; i < MAX_CONNECTIONS; i++ )
    {
      if( FD_ISSET(&exc_fd, connections[i]) )
      { /* error occurred on this connection; clean up and set connection[i] to 0 */ }
      else
      {
        if( FD_ISSET(&in_fd, connections[i]) )
        { /* handle input */ }
        if( FD_ISSET(&out_fd, connections[i]) )
        { /* handle output */ }
      }
    }
  }
}
于 2008-11-27T05:43:04.633 に答える
0

編集: 以下の回答は、質問の誤解に基づいています。OP のコードは、リモート サーバーに対して open() したソケットで実際に recv() を試みています。後世のために左下のもの。


あなたのコードをもっと見せてください。

ただし、いくつかの観察事項:

  • ソケットlisten()ingですか?
  • accept()ed着信接続はありますか
  • recv()TCP ソケットで使用するのは少し珍しいです。read()代わりに使用してください。
  • 111 エラー コードをローカル エラー文字列に変換するために使用strerror()します。各 UNIX O/S は、数字から Exxx エラー コードへの独自のマッピングを持つことができるため、システム上のこのエラーが何であるかを知ることはできません。

通常のコード ループ (シングル スレッドの非フォーク アプリの場合) は次のようになります。

s = socket();
err = listen(s, n); // n = backlog number
while (1) {
    int fd = accept(s, &addr, sizeof(addr));
    while (1) {
        int numrecv = read(fd, ...);
        // break if eof
    }
    close(fd);
}
close(s);
于 2008-11-26T14:27:11.753 に答える