클라이언트 응용 프로그램이 닫힐 때까지 클라이언트에서 서버로의 연결이 열려있는 클라이언트/서버 응용 프로그램에서 작업하고 있습니다.다른 쪽 끝이 닫힐 때 소켓이 등록되지 않음
클라이언트가 데이터를 읽는 동안 서버 응용 프로그램이 예기치 않게 다운 된 경우 클라이언트에서 예외로 처리하고 예외를 catch 한 다음 해당 예외를 인수로 발생 시키길 원합니다.
나는이 시스템이 작동하는지 테스트해야한다고 생각하는 테스트를 작성했지만, 테스트중인 객체는 중단 점을 넣은 다음 계속 진행하지 않으면 소켓이 닫혔다는 것을 등록하지 않는 것처럼 보입니다.
시험의 중요한 부분은 다음과 같다 다음 TcpListener
객체 listener
가 루프백 주소를 듣고
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);
.
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
은 서버가 종료되었음을 알 수 있습니까?
루프백 주소에서 가능합니까?
모든 코드를 죄송합니다. 방법을 줄이는 방법을 생각할 수 없었습니다.
포인터를 제공해 주셔서 감사합니다. 루프백 이외의 다른 주소를 사용해 보겠습니다. –
Markus가 정확합니다. [연결이 여전히 실행 가능한지 여부를 확인하려면 데이터를 보내야합니다.] (http://nitoprograms.blogspot.com/2009/05/detection-of-half-open-dropped.html). –
우수한 링크. 고마워, 스티븐. 나는 하트 비트를 추가했으며 문제는 사라졌다. –