2013-12-13 2 views
1

청취자와 TCPClient간에 스트림을 열어야하는 상황에 처해 있습니다. 스트림이 열리면 클라이언트는 메시지 스트림을 보내고 각각에 대해 ACK를 보냅니다. 정해진 시간 (기본적으로 5 분) 동안 아무런 메시지도받지 못하면 서버와의 연결을 끊고 새 연결을 청취합니다.TCP 스트림의 연결이 끊어 졌는지 확인

수신기에는 통신을 시도하는 클라이언트가 하나만 있어야합니다. 사양에는 모든 메시지가 전송 될 때까지 스트림을 열어 놓아야한다는 내용이 있으며 이는 장치가 며칠 이상 연결되어 있음을 의미 할 수 있습니다. 불행히도 클라이언트는 타사 소프트웨어이므로 각 메시지가 끝난 후 연결이 끊어지지 않을 것이라고 보장 할 수는 없습니다.

제 질문은 클라이언트의 연결이 끊어 졌는지 어떻게 알 수 있습니까? 나는 이미이 질문에 대한 답이 몇 가지있다는 것을 알고 있지만 스트림에 쓸 필요가 있다고 말합니다. 예외가 있으면 연결이 끊어졌습니다. 이 작업을 수행하는 코드를 작성했지만 일부 클라이언트가 ACK가 아닌 수신 메시지를 처리하도록 설정되어 있지 않음을 알았습니다. 지금까지 모든 오류 메시지가 기록되지만이 "핑"으로 인해 클라이언트 중 하나가 손상 될 수 있습니다.

각 메시지가 끝난 후 연결을 닫을 수 있지만 하나 이상의 클라이언트가 하나의 스트림에서 모든 메시지를 수신 할 때까지 일련의 모든 메시지를 계속 보내려고하므로이 솔루션에서 작동하지 않습니다 .

NetworkStream.ReadTimeout을 1 초와 같은 작은 값으로 설정할 수 있지만 예외가 발생할 때마다 예외가 발생하고 흐름 제어를위한 예외를 사용하면 좋은 코드가 아닙니다. 그것 핑 할 때). 다음은

내가 지금 무슨의 조각입니다 : 좀 더 검색 후

while (bytesRead == 0 && isConnected && isListening) 
{ 
    if (stream.CanRead && stream.DataAvailable) 
    bytesRead = stream.Read(receivedBytes, 0, BufferSize); 
    else 
    { 
     if (++pingCount % 100 == 0) 
     { 
      // Ping the server every 10 seconds to confirm the connection 
      pingCount = 0; 
      try 
      { 
       stream.Write(ping, 0, ping.Length); 

       // client.Connected gives the status of the connection at the last communication 
       if (!client.Connected) 
        isConnected = false; 
      } 
      catch (Exception) 
      { 
       // If an exception is thrown, then the connection is closed 
       isConnected = false; 
      } 
     } 
     Thread.Sleep(100);  // Wait and try again 
    } 
} 
+0

작성시 재앙이 들립니다. 그런 아주 기본적인 것들에 대해 동의 할 수 없다면, 당신은 일을하게하는 시간을 가질 것입니다. 명세를 써서 힘들게 만드십시오. –

+0

우리가 이것을 할 수 있다면 훨씬 더 쉬울 것이라는 데 동의하지만 우리는 기존의 여러 클라이언트와 협력하고 있으며 어떤 소프트웨어가 메시지를 보낼지 모르기 때문에 최대한 포괄적이어야합니다. 메시지 내용 – Tim

답변

1

, 나는하여 TcpClient에서 소켓에 액세스하는 방법을 알 수 있었다. 이 작업이 끝나면 Poll을 사용하여 연결이 아직 열려 있는지 확인할 수있었습니다. 내 코드는 다음과 같습니다 :

try 
{ 
    if (client.Client.Poll(1000, SelectMode.SelectRead) && client.Client.Available == 0) 
    { 
     isConnected = false; 
    } 
} 
catch (Exception) 
{ 
    // If an exception is thrown, then the connection is closed 
    isConnected = false; 
} 

Client.Poll은 연결이 보류, 다시 폐쇄 종료되면 true를 반환하거나, 사용 가능한 데이터가있다. Client.Available을 확인하고 데이터가없는 경우 연결을 닫아야합니다. 이것은 방금은 아니지만 내 목적을 위해 작동합니다. 단지 듣기로 돌아 가기 때문입니다.

이 솔루션은 zendar에서 제공되었으며 here입니다.

관련 문제