通过 TCP 发送长 XML
我正在服务器端使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的客户端代码假设整个消息将在一次调用
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.