我正在处理客户端/服务器应用程序,其中从客户端到服务器的连接保持打开状态,直到客户端应用程序关闭。当另一端关闭时,套接字未注册
如果服务器应用程序意外关闭,当客户端读取数据,我希望客户将此视为一个例外,但随后捕获异常,并与异常作为参数引发事件。
我写了一个测试,我认为应该测试,该系统的工作原理,但我的目标测试似乎没有注册,除非我把一个破发点,然后继续关闭套接字。
测试的重要组成部分,是这样的:
StreamingMonitor sm = new StreamingMonitor();
bool errored = false;
string msg = "";
sm.ErrorOccurred += (s, a) =>
{
errored = true;
msg = a.Exception.Message;
};
sm.Enabled = true;
client = listener.AcceptTcpClient();
client.GetStream().Write(BitConverter.GetBytes(10000), 0, 4);
client.Close();
while(!errored)
{}
Assert.AreEqual("A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call", msg);
的TcpListener
对象listener
监听回送地址。
的StreamingMonitor
开始侦听数据的长度被启用时,它检索。数据的长度总是假定为符合一个有符号的32位整数。
当收到消息长度时,调用这个方法。
private void GotMessageLength(IAsyncResult asyncResult)
{
try
{
client.Client.EndReceive(asyncResult);
if(firstMessage)
{
firstMessage = false;
if (Connected != null)
{
Connected(this, new EventArgs());
}
}
int msgLen = BitConverter.ToInt32(messageLength, 0);
byte[] message = new byte[msgLen];
List<byte> lbMessage = new List<byte>();
int bytesReturned = client.Client.Receive(message);
int remaining = (msgLen < bytesReturned) ? bytesReturned - msgLen : msgLen - bytesReturned;
if(remaining > 0)
{
if (bytesReturned > 0)
{
for (int i = 0; i < bytesReturned; i++)
{
lbMessage.Add(message[i]);
}
}
while(remaining > 0)
{
if(!client.Connected)
{
throw new SocketException((int)SocketError.Shutdown);
}
bytesReturned = client.Client.Receive(message);
remaining = (remaining < bytesReturned) ? bytesReturned - remaining : remaining - bytesReturned;
if (bytesReturned > 0)
{
for (int i = 0; i < bytesReturned; i++)
{
lbMessage.Add(message[i]);
}
}
}
message = lbMessage.ToArray();
}
MessageReceived(this, new MessageReceivedEventArgs(message));
if (Enabled)
{
client.Client.BeginReceive(messageLength, 0, 4, SocketFlags.None, GotMessageLength, null);
}
}
catch (SocketException ex)
{
if(ErrorOccurred != null)
{
ErrorOccurred(this, new ErrorEventArgs(ex));
}
}
catch (ObjectDisposedException)
{
}
}
该方法从网络流中读取数据,直到它读取到指定的字节数。如果远程连接关闭,则应该引发套接字异常。
但是,单元测试陷入无限循环,等待发生错误,因为StreamingMonitor
中的套接字从未意识到另一端已关闭。
我怎样才能让SteamingMonitor
意识到,服务器已经走了吗?
这是可能的回环地址?
对不起,所有的代码,我想不出如何削减的方法了。
感谢您的指点。我会尝试使用不同于回送的地址。 – 2010-08-17 11:24:54
Markus是正确的; [你必须发送数据来检测连接是否仍然可行](http://nitoprograms.blogspot.com/2009/05/detection-of-half-open-dropped.html)。 – 2010-08-17 12:17:56
优秀的链接。谢谢,史蒂芬。我心跳加速,问题消失了。 – 2010-08-17 12:45:32