簡體   English   中英

通過TCP客戶端套接字接收數據的問題

[英]Problems receiving data over a TCP client socket

我正在嘗試在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
}

...

連接到服務器后,在發送兩行數據后,服務器應該收到一些信息,但是當我運行它時,它會打印:

收稿日期:

然后繼續只是坐在那里直到我迫使它關閉。

**編輯**當我做喬納森告訴我要做的事情時,我得到以下內容:

數:-1,錯誤:111,收到:

這意味着它的錯誤,但我該怎么辦呢?

打印出收到的字節數 - 它可能為零,但確認一下。

值得檢查的是,您沒有收到錯誤 - 因此會使緩沖區下溢。

[ 注意:從這里開始是Pax的工作 - 謝謝你 ,我已經將它轉換為社區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輸入的內容,然后鍵入hello接着ENTER兩次:

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>

你應該看到類似的東西。

我強烈推薦Beej的網絡編程指南

本節特別為客戶提供完全符合要求的代碼。

編輯:下面的答案是基於對問題的誤解 - OP的代碼實際上是試圖在打開()編輯到遠程服務器的套接字上recv()。 后面的東西為后代。


請顯示更多代碼。

但有幾點意見:

  • 套接字listen()ing
  • accept()ed傳入的連接
  • 在TCP套接字上使用recv()有點不尋常。 請改用read()
  • 使用strerror()將111錯誤代碼轉換為本地錯誤字符串 - 每個UNIX操作系統都可以有自己的數字映射到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);

無限循環是什么? 為什么不使用select(),以便在只讀取實際數據時調用recv()?

在以前的生活中,我為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 */ }
      }
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM