[英]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
傳入的連接 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.