c#网络陌生感

本文关键字:网络 | 更新日期: 2023-09-27 18:21:10

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

我有一个方法,PlayerReadLoop,它传递了一个琐碎的Player对象,还传递了tcpClient对象。这个方法还不完整,并且不依赖于它正在传递的Player对象,所以,不需要提供任何关于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();

c#网络陌生感

Source;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文档,你会发现很多有趣的地方可以解释这一点。不幸的是,我现在无法分享链接。

我正在一个小型网络服务器上工作

你见过开源的c网络通讯库networkComms.net吗?它就像即插即用一样好,所以你可以立即启动并运行。另外,你遇到的大多数问题都已经解决了。