【发布时间】:2013-01-11 05:28:57
【问题描述】:
我创建的应用程序出现了一些问题。一般情况(以下描述与问题不是1-1相关的):我有一个WCF客户端-服务器应用程序,用于在多个站点收集数据。客户端检索本地数据(一些文件等),将其发送到数据中心的服务器,该服务器对其进行处理。客户端从本地主机获取其大部分数据,但其中一些是从 LAN 上的不同服务器检索的。这是我的问题开始的地方。我必须创建一个将数据发送到指定客户端的第三个应用程序。在这篇文章的提醒中,我将客户端和服务器称为同一 LAN 上的应用程序(而不是上面数据中心中的服务器)
我尝试使用命名管道,它在同一主机上的进程间非常出色,但服务器到服务器的速度非常慢。 (如果有人知道为什么会这样,请不要犹豫告诉我。一些测试高达 1000 毫秒,发送和接收仅几个字节)
所以我开始使用 TcpClient 类。测试显示响应比 NP 等效项快得多,因此我决定使用此选项。
现在,当客户端和服务器都按应有的方式启动和结束时,一切都很好。当服务器启动,客户端已经连接,服务器正在等待它的 stream.Read() 方法,然后客户端应用程序退出时,问题就出现了:
Unable to read data from the transport connection: De externe host heeft een verbinding verbroken.(第二部分翻译:一个现有的连接被远程主机强行关闭。)
目前我用 Try-Catch 语句包装了整个部分,在 IoException 上重新启动了整个部分。这确实有效,但是当我阅读了几篇关于“异常应该是异常的东西!”的帖子时,感觉不太好。
所以最后的问题是:如何避免这个异常? (在现实生活中保持服务器和客户端应用程序之间连接的正常方式是什么?)
服务器 TcpListener serverSocket = new TcpListener(System.Net.IPAddress.Any, 8888); TcpClient clientSocket = default(TcpClient);
while (true)
{
serverSocket.Start();
clientSocket = serverSocket.AcceptTcpClient();
while ((true))
{
try
{
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);//THIS THROWS THE EXCEPTION WHEN A CLIENT QUITS
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Server response " + DateTime.Now.ToString("HH:mm:ss,fff");
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
int len = sendBytes.Length;
networkStream.WriteByte((byte)(len / 256));
networkStream.WriteByte((byte)(len & 255));
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
}
catch (System.IO.IOException ex)
{
Console.WriteLine(ex.ToString());
break;
}
}
clientSocket.Close();
serverSocket.Stop();
}
}
客户
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
private void button2_Click(object sender, EventArgs e)
{
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("Message from Client$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
int len = serverStream.ReadByte() * 256;
len += serverStream.ReadByte();
byte[] inStream = new byte[len];
serverStream.Read(inStream, 0, len);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
msg("Data from Server : " + returndata);
}
private void button1_Click_1(object sender, EventArgs e)
{
clientSocket.Connect("127.0.0.1", 8888);
}
【问题讨论】:
-
当一方强行断开连接时,您期望会发生什么?我认为这种情况有一个例外是正常的。也许您应该修改双方以不强制关闭连接。
-
与您提出的问题不完全相关,但仅仅因为您正在执行特定字节数的
Read,并不意味着这将是多少字节通过调用读取,需要检查返回值,如有必要,再次调用Read,直到收到预期的字节数。 -
@usr,好的,谢谢,但是处理这种情况的正常方法是什么?含义:这个想法是应用程序在工作时间内每分钟 24-7 小时通信,晚上可能根本没有交通。我应该在每次发送后关闭连接,还是只接受网络故障等异常,然后重新启动它?或者当服务器正在等待 Read() 时,客户端是否可以通知服务器它将关闭?
标签: c# sockets networkstream