通过 TCP 发送长 XML

发布于 2024-12-11 23:50:37 字数 4377 浏览 1 评论 0原文

我正在服务器端使用 TcpListener 通过 TCP 发送一个对象(类名 House),以响应从 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());
}

我已在出现错误的代码上进行了标记。

是因为消息太长吗?

I'm sending an object (class name House) over TCP using the TcpListener on the server side in response to any message received from the TcpClient.

When the message is received, it is currently populating a text box named textBox1.

If I send a line of text, it works fine. You'll notice that I have a redundant line "Hello, I'm a server" for testing this purpose. But when I send the XML, it is cutting it off prematurely.

When I send serialised XML in to the stream, I'm also receiving this error from the server side:

Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host.

Here's my server code

// 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();
}

Client code

// 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());
}

I've marked on the code where the error is appearing.

Is it because the message is too long?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

脱离于你 2024-12-18 23:50:37

您的客户端代码假设整个消息将在一次调用 Read(...) 方法中完成,这是绝对错误的。来自 MSDN 文档"即使尚未到达流的末尾,实现也可以自由地返回比请求更少的字节。”

对于 1024 字节的 XML 文档,您可能必须调用 Read(. ..) 1024次获取完整消息。

实际上,您最好在发送 XML 之前发送四字节长度,以便客户端知道需要多少数据。客户端将读取四个字节,将其转换为整数长度,然后读取更多字节,然后将这些字节转换为 XML。

Your client code is assuming that the entire message will come through in one call to the Read(...) method, which is absolutely wrong. From the MSDN docs: "An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached."

It's possible that, for a 1024-byte XML document, you may have to call Read(...) 1024 times to get the entire message.

Really, you'd do well to send a four-byte length before you send the XML, so that the client knows how much data to expect. The client will read four bytes, convert that to an integer length, then read that many more bytes, then turn those bytes into XML.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文