Отправка длинного XML через TCP - PullRequest
1 голос
/ 25 октября 2011

Я отправляю объект (имя класса House) через TCP, используя TcpListener на стороне сервера в ответ на любое сообщение, полученное от TcpClient.

Когда сообщение получено, он в настоящее время заполняет текстовое поле с именем textBox1.

Если я отправляю строку текста, он работает нормально.Вы заметите, что у меня есть лишняя строка «Здравствуйте, я сервер» для тестирования этой цели.Но когда я отправляю XML, он преждевременно обрезает его.

Когда я отправляю сериализованный XML в поток, я также получаю эту ошибку со стороны сервера:

Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом.

Вот мой код сервера

// Set the variables for the TCP listener
Int32 port = 14000;
IPAddress ipaddress = IPAddress.Parse("132.147.160.198");
TcpListener houseServer = null;

// Create IPEndpoint for connection
IPEndPoint ipend = new IPEndPoint(ipaddress, port);

// Set the server parameters
houseServer = new TcpListener(port);

// Start listening for clients connecting
houseServer.Start();

// Buffer for reading the data received from the client
Byte[] bytes = new Byte[256];
String data = "hello, this is a house";

// Show that the TCP Listener has been initialised
Console.WriteLine("We have a TCP Listener, waiting for a connection...");

// Continuing loop looking for 
while (true)
{

    // Create a house to send
    House houseToSendToClient = new House
    {
        house_id = 1,
        house_number = 13,
        street = "Barton Grange",
        house_town = "Lancaster",
        postcode = "LA1 2BP"
    };

    // Get the object serialised
    var xmlSerializer = new XmlSerializer(typeof(House));

    using (var memoryStream = new MemoryStream())
    {
        xmlSerializer.Serialize(memoryStream, houseToSendToClient);
    }

    // Accept an incoming request from the client
    TcpClient client = houseServer.AcceptTcpClient();

    // Show that there is a client connected
    //Console.WriteLine("Client connected!");

    // Get the message that was sent by the server
    NetworkStream stream = client.GetStream();

    // Blank int
    int i;

    // Loop for receiving the connection from the client

    // >>> ERROR IS ON THIS LINE <<<
    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
    {
        Console.WriteLine("here");

        // Take bytes and convert to ASCII string
        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);

                Console.WriteLine("Received s, return house");

                // Convert the string to a byte array, ready for sending
                Byte[] dataToSend = System.Text.Encoding.ASCII.GetBytes("Hello, I'm a server");

                // Send the data back to the client
                //stream.Write(dataToSend, 0, dataToSend.Length);

                // Send serialised XML in to the stream
                xmlSerializer.Serialize(stream, houseToSendToClient);

    }

    // Close the connection
    client.Close();
}

Код клиента

// Get the object serialised
var xmlSerializer = new XmlSerializer(typeof(House));

// Set the variables for the TCP client
Int32 port = 14000;
IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
IPEndPoint ipend = new IPEndPoint(ipaddress, port);

string message = "s";

try
{

    // Create TCPCLient
    //TcpClient client = new TcpClient("localhost", port);
    TcpClient client = new TcpClient();

    // Convert the string to a byte array, ready for sending
    Byte[] dataToSend = System.Text.Encoding.ASCII.GetBytes(message);

    // Connect using TcpClient
    client.Connect(ipaddress, port);

    // Client stream for reading and writing to server
    NetworkStream stream = client.GetStream();

            // Send the data to the TCP Server
            stream.Write(dataToSend, 0, dataToSend.Length);
            //xmlSerializer.Serialize(stream, houseToSend);                        

            // Buffer to store response
            Byte[] responseBytes = new Byte[256];

            string responseData = String.Empty;

            // Read the response back from the server
            Int32 bytes = stream.Read(responseBytes, 0, responseBytes.Length);
            responseData = System.Text.Encoding.ASCII.GetString(responseBytes, 0, bytes);
            textBox1.Text = responseData;


        // Close the stream and the client connection
        stream.Close();
        client.Close();

}
catch (SocketException e)
{
    MessageBox.Show(e.ToString());
}
catch (Exception e)
{
    MessageBox.Show(e.ToString());
}

Я отметил в коде, где появляется ошибка.

Это потому, что сообщение слишком длинное?

1 Ответ

2 голосов
/ 25 октября 2011

Ваш клиентский код предполагает, что все сообщение будет передано за один вызов метода Read(...), что абсолютно неверно.Из документов MSDN : "Реализация может вернуть меньше байтов, чем запрошено, даже если конец потока не достигнут."

Возможно, чтодля 1024-байтового XML-документа вам, возможно, придется позвонить Read(...) 1024 раза, чтобы получить все сообщение.

На самом деле, вы бы хорошо отправили четырехбайтовую длину, прежде чем отправлять XML, так что клиент знает, сколько данных ожидать.Клиент прочитает четыре байта, преобразует их в целочисленную длину, затем прочитает столько больше байтов, а затем превратит эти байты в XML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...