NetworkStream никогда не записывает данные - PullRequest
1 голос
/ 27 августа 2011

Хорошо, поэтому я понимаю всю идею, что 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 голосов
/ 27 августа 2011

Хорошо, поэтому я понимаю всю идею о том, что 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);
        }
    }
}
...