2012-01-23 55 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?它与即插即用一样好,因此您可以立即启动并运行。再加上你遇到的大部分问题都已经解决了。