2012-01-23 59 views
0

我正在一個小型的網絡服務器上工作,而我正在從最新版本的MonoDevelop開始。c#網絡奇怪

我有一個方法,PlayerReadLoop,它傳遞了一個普通的Player對象,並且還傳遞了一個tcpClient對象。這個方法還沒有完成,並且不依賴於它傳遞的Player對象,所以,不需要給玩家任何信息。 TcpClient已經正確初始化了,因爲我已經在傳遞過程中成功地通過tcpClient發送了消息。

這裏是方法:

private void playerReadLoop(Player p, TcpClient c) 
{ 
    byte[] message = new byte[4096]; 
    int bytesRead; 
    NetworkStream clientStream = c.GetStream(); 
    while (true) 
    { 
     bytesRead = 0; 
     try 
     { 
      bytesRead = clientStream.Read(message, 0, 4096); 
     } 
     catch 
     { 
      Console.WriteLine("ERROR"); 
      break; 
     } 
     if (bytesRead == 0) 
     { 
      Console.WriteLine("Disconnected"); 
      break; 
     } 

     ASCIIEncoding encoder = new ASCIIEncoding(); 
     Console.WriteLine(encoder.GetString(message, 0, bytesRead)); 

    } 
} 

出於某種原因,上面的代碼不工作!你看,

當我圍繞着兩條線:

SCIIEncoding encoder = new ASCIIEncoding(); 
Console.WriteLine(encoder.GetString(message, 0, bytesRead)); 

與符號,我的客戶是否將消息發送,clientStream.Read經過,並返回零個字節,表示斷線。我的客戶根本沒有發送任何信息,當然也沒有斷開連接。

當兩條線都沒有標出時,clientStream.read從不通過。我的客戶是否發送消息。

現在,如果這並不奇怪,直接在我的tcpClient初始化後(在與tcpClient初始化相同的方法中)上面的代碼,代碼WORKS!我沒有對tcpClient做任何事情,我只是直接將它傳遞給上面的函數,並使用使用tcpClient初始化的Player對象。播放器對象對tcpClient不做任何事情,只是將它存儲在其中一個變量中。我不明白如何將這些代碼放入它自己的方法中導致這種行爲上的淫穢差異!

客戶端代碼很簡單:

TcpClient client = new TcpClient(); 

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 21255); 

client.Connect(serverEndPoint); 

NetworkStream clientStream = client.GetStream(); 

ASCIIEncoding encoder = new ASCIIEncoding(); 
byte[] buffer = encoder.GetBytes("Hello Server!"); 

clientStream.Write(buffer, 0 , buffer.Length); 
clientStream.Flush(); 
+0

你是什麼意思的「當我圍繞兩條線:[...]與符號」? – arx

+0

line1; 2號線;成爲/ * line1; line2; */ –

+0

「我的客戶根本沒有發送任何內容,當然也沒有斷開連接。」但是服務器呢?你怎麼能確定該連接的服務器端沒有丟失你的連接。在網絡代碼故障排除期間運行Wireshark是必須的。 – tcarvin

回答

0

來源; http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.flush.aspx

在網絡流上調用刷新沒有任何效果,所以它不應該在您的代碼中開始。

讀寫操作通常阻塞插座上的操作。因此他們會等到操作完成。在閱讀&寫入網絡流之前,最好檢查它們是否可以真正寫入或讀取。這是屬性。 (更多信息在http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.write.aspx

此外,因爲讀取可以返回0,它並不意味着代碼中寫的客戶端'斷開連接'。這只是意味着接收緩衝區中沒有字節可用於讀取。這也意味着讀取將保持阻塞默認直到數據實際上是beeing發送。

如果您未收到數據,請檢查兩個客戶端&服務器上的端口&連接設置,以使它們匹配。

編輯 僅僅因爲你寫的東西的NetworkStream,並不意味着它就會通過電線直接發送。你的代碼和實際套接字之間有一個緩衝區。沒有控制這個緩衝區,只有Windows控制它。這就是爲什麼你的代碼和實際發送之間有時會有延遲。

它也解釋了爲什麼某些設置或代碼配置似乎沒有直接影響。這些信息隱藏得很好,而不是在MSDN上,但是如果您深入瞭解Microsoft有關套接字通信的technet文檔,您會發現更多的解釋這一點的多汁點。不幸的是,我目前無法分享鏈接。

+0

奇怪的是,當代碼在我執行過程中的不同位置時,代碼完美工作 - 所以我確定知道連接信息是正確的,並且檢查零字節似乎會導致讀取阻塞,直到發送了某些內容,或者客戶端斷開連接,所以,不知道。然後有這樣的事實,試圖從流中讀取以某種方式阻止它斷開連接!這是非常奇怪的行爲,但我會嘗試檢查等待數據流準備就緒 –

+0

當讀取流沒有任何可讀的時候,返回0字節是正確的!出於某種原因,現在每件事都在起作用,我添加了while循環來等待流激活,儘管它們還沒有真正被調用。 –

+0

編輯我的帖子,給你一個可能的解釋。 –

0

我有點網絡服務器上的工作

假如你遇到了開源的C#網絡通信庫networkComms.net?它與即插即用一樣好,因此您可以立即啓動並運行。再加上你遇到的大部分問題都已經解決了。