c#网络陌生

时间:2012-01-23 00:08:45

标签: c# networking

我正在开发一个小型网络服务器,我是从MonoDevelop的最新版本开始的。

我有一个方法,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的方法中),代码就可以了!我没有对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();

2 个答案:

答案 0 :(得分:0)

  

我正在开发一个小型网络服务器

您是否遇到过开源c#网络通信库networkComms.net?它就像即插即用一样好,所以你可以立即启动并运行。此外,您遇到的大部分问题都已经解决了。

答案 1 :(得分:0)

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

在网络流上调用Flush没有任何效果,因此它不应该在您的代码中开始。

读取和写入操作通常在套接字上阻塞操作。因此他们会等到操作完全完成。在阅读之前写入网络流,您最好检查它们是否可以实际写入或读取。那里有属性。 (更多信息请见http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.write.aspx

另外,因为Read可以返回0,这并不意味着客户端“断开连接”,如代码中所写。它只是意味着接收缓冲区上没有可用的字节可供读取。这也意味着默认情况下,Read将保持阻塞状态,直到实际发送数据为止。

如果您没有收到数据,请检查端口&客户端和客户端的连接设置服务器使它们匹配。

修改 仅仅因为你在网络流上写了一些东西,并不意味着它直接通过网络发送。代码和实际套接字之间有一个缓冲区。无法控制此缓冲区,只有Windows控制它。这就是为什么你的代码和实际发送之间有时会出现延迟的原因。

它还解释了为什么某些设置或代码配置似乎没有直接影响。这些信息很好地隐藏,而不是在MSDN上,但如果你深入了解微软关于套接字通信的technet文档,你会发现很多有用的东西可以解释这一点。不幸的是,我目前无法分享链接。