NetworkStream从不写数据

时间:2011-08-27 06:35:54

标签: c# .net networking tcp tcpclient

好吧,所以我理解TCP基于流而不是基于消息的整个想法 - 我不关心。

我想要做的是尝试简单地序列化某些内容并通过网络将其发送到另一个使用基于消息的协议的应用程序。

问题在于,无论何时我将数据序列化(我正在序列化为XML),然后将其写入网络流,这种糟糕的事情永远不会写出来 - 永远。直到我关闭程序并关闭流,实际上流才会发送数据。到底发生了什么 - TCP是否在等待发送足够的数据?它在等我的东西吗? (我怀疑前者,因为我可以做简单的写行,并且它做得很好。)

以下是我的客户的代码:

        TcpClient client = new TcpClient();
        client.Connect(IPAddress.Parse("127.0.0.1"), 10100);
        NetworkStream ns = client.GetStream();
        StreamWriter writer = new StreamWriter(ns);

        ListenerThread th = new ListenerThread(new StreamReader(ns));
        new Thread(th.run).Start();

        XmlSerializer serializer = new XmlSerializer(typeof(Message), new Type[] {typeof(AuthenticationMessage), typeof(ChangeChatRoomMessage), typeof(ChangePasswordMessage), typeof(ConnectionStatusMessage), typeof(InitializeMessage), typeof(StatusMessage), typeof(SuccessMessage), typeof(TextMessage)});

        string file =  "<some test xml file>";
        while(true)
        {
            FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read);
            StreamReader reader = new StreamReader(stream);
            Message newmsg = (Message)serializer.Deserialize(reader);
            stream.Close();

            serializer.Serialize(writer, newmsg);
            writer.Flush();

            file = Console.ReadLine();
        }

以下是服务器的代码:

    public void HandleMessage()
    {
        Message msg = (Message)serializer.Deserialize(reader);
        Console.WriteLine("Read Message " + msg.GetType());
    }

    public void Start()
    {
        while(true)
        {
            Socket socket = listener.AcceptSocket();
            NetworkStream stream = new NetworkStream(socket);
            reader = new StreamReader(stream);
            HandleMessage();
            stream.Close();
        }
    }

我的程序现在已运行20分钟,并且没有任何内容已发送到服务器。我尝试了我能想到的一切,刷新我的编写器缓冲区(TextWriter,显然不是NetworkStream),并将客户端设置为NoDelay等等......发生了什么以及为什么?

1 个答案:

答案 0 :(得分:0)

  

好吧,所以我理解TCP基于流的整个想法   不是基于消息 - 我不关心。

实际上这非常重要,你应该关心它。将数据发送到服务器时,您不仅应该尝试发送一些消息,还应该定义一些协议(或使用现有协议),客户端向服务器指示该协议,例如它打算发送多少数据。

所以这是一个如何进行的例子。在此示例中,客户端将前消息的长度作为前4个字节发送。

服务器:

class Program
{
    static void Main()
    {
        var listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, 10100));
        listener.Start();
        while (true)
        {
            using (var client = listener.AcceptTcpClient())
            using (var stream = client.GetStream())
            using (var reader = new BinaryReader(stream))
            {
                // The first 4 bytes of the message will indicate
                // the total message length
                var length = reader.ReadInt32();
                var buffer = reader.ReadBytes(length);
                Console.WriteLine("Received {0} bytes from client:", length);
                Console.WriteLine("{0}", Encoding.UTF8.GetString(buffer));
            }
        }
    }
}

客户端:

class Program
{
    static void Main()
    {
        using (var client = new TcpClient("127.0.0.1", 10100))
        using (var stream = client.GetStream())
        using (var writer = new BinaryWriter(stream))
        {
            var message = "<some test xml file>";
            var buffer = Encoding.UTF8.GetBytes(message);
            // Send the total message length in the first 4 bytes
            // so that the server knows how much it has to read
            writer.Write(buffer.Length);
            writer.Write(buffer);
            Console.WriteLine("Successfully sent {0} bytes to server", buffer.Length);
        }
    }
}