Сериализация XML через проблемы TCP - PullRequest
0 голосов
/ 10 октября 2018

Просто тестируем простой пример программы для отправки сериализованного объекта XML через TCP.Я обнаружил, что до тех пор, пока я не закрою поток или TcpClient на стороне, которая отправляет сериализованный объект, получатель никогда не получит его.

class Program
{
    private static XmlSerializer positionSerializer = new XmlSerializer(typeof(GazePosition));

    static void Main(string[] args)
    {
        new Thread(Server).Start();
        new Thread(Client).Start();

        Console.ReadLine();
    }

    static void Server()
    {
        TcpListener listener = new TcpListener(IPAddress.Loopback, 30000);
        listener.Start();

        TcpClient client = listener.AcceptTcpClient();
        Stream stream = client.GetStream();
        StreamReader reader = new StreamReader(stream);
        var cmd = reader.ReadLine();
        if (cmd == "GetPosition")
        {
            Console.WriteLine("Received GetPosition Command");
            GazePosition pos = new GazePosition(-5, 5);
            positionSerializer.Serialize(stream, pos);
        }
        //client.Close();
        listener.Stop();
    }

    static void Client()
    {
        TcpClient client = new TcpClient();
        client.Connect(IPAddress.Loopback, 30000);
        Stream stream = client.GetStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.WriteLine("GetPosition");
        writer.Flush();
        var pos = (GazePosition)positionSerializer.Deserialize(stream);
        Console.WriteLine("Received: {0}", pos);
        stream.Close();
        client.Close();
    }
}

[Serializable]
[XmlRoot("GazePosition")]
public class GazePosition
{
    [XmlElement("X")]
    public float X;
    [XmlElement("Y")]
    public float Y;

    public GazePosition()
    {

    }

    public GazePosition(float x, float y)
    {
        X = x;
        Y = y;
    }

    public override string ToString()
    {
        return string.Format("{0},{1}", X, Y);
    }
}

Это выводит только:

Полученная команда GetPosition

Однако, если я раскомментирую client.Close()

Это распечатывает:

Полученная команда GetPosition

Получено -5, 5

Мне бы хотелось, чтобы этот пример можно было масштабировать до получения нескольких команд, но это больно, когда я вынужден закрывать поток каждый раз, когда получаю команду.Если бы кто-то мог объяснить мне, почему это происходит, я был бы очень благодарен!

1 Ответ

0 голосов
/ 10 октября 2018

Здесь вам не хватает того, что вы должны читать из потока TcpClient на стороне клиента.Пожалуйста, посмотрите, что я просто сделал, чтобы заставить его работать.Помните, что это просто пример.

    writer.WriteLine("GetPosition");
    writer.Flush();

    //Just like you did you should seperate the payload
    //Either by size or new line or some special key you set
    byte[] buffer = new byte[1024];
    stream.Read(buffer, 0, buffer.Length);
    using (var ms = new MemoryStream(buffer))
    {
        var gazePos = (GazePosition)positionSerializer.Deserialize(ms);
        //DOSTUFF
    }
    //Added code finished

Вот простая библиотека уровня beta.Возможно, вы захотите взглянуть → Простой сервер

Редактировать: я также посмотрел на NetworkStream Dispose метод.Он имеет собственные вызовы Windows API, поэтому я не могу углубляться в детали реализации. Однако, как вы можете видеть здесь , во время постепенного завершения работы, которое происходит при удалении сетевого потока, отправляется FD_CLOSE

...