2011-02-02 7 views
2

TcpClient 및 TcpListener를 사용하여 네트워크를 통해 통신하는 응용 프로그램이 있습니다. 그러나 클라이언트에서 TcpClient.Close를 호출하여 서버와의 연결을 끊으면 서버가 전혀 반응하지 않습니다.TcpClient.Close가 연결을 닫지 않습니다.

이제이 질문에 대한 답변을 this의 사본으로 작성하고 해결 방법을 here으로 찾을 수 있습니다. 이미 내가 이것을 찾았고 시도해 보았습니다. 도움이되지 않습니다. 또한 TcpClient.Close, TcpClient.GetStream().Close()TcpClient.Dispose의 조합을 시도해 보았습니다. 아무것도 작동하지 않습니다.

코드는 아무 것도 주목할 가치가 없습니다. 모든 변수를 다시 설정하고 모든 네트워크 리소스를 닫는 클라이언트의 Disconnect 메서드입니다. 서버에는 TcpClient.Connected이 true인지 아닌지를 확인하는 루프가 있고, 틀린 경우 루프에서 빠져 나와 스레드를 종료해야합니다.

아이디어가 있으십니까?

답변

8

TcpClient.Connected은 거의 무시해야합니다. 기본적으로 마지막 통신이 성공했는지 여부를 나타냅니다. MSDN (강조 광산)에서 : Connected 속성은 가장 최근의 작업과 연결 상태를 반영하기 때문에

보내거나 현재 상태를 확인하는 메시지가 나타납니다을 시도한다. 메시지 보내기가 실패한 후이 속성은 더 이상 true를 반환하지 않습니다. 이 동작은 의도적으로 설계된 동작입니다. 테스트와 보내기/받기 사이의 시간에 연결이 손실되었을 수 있으므로 안정적으로 연결 상태를 테스트 할 수 없습니다. 코드는 소켓이 연결되어 있다고 가정하고 실패한 전송을 정상적으로 처리합니다.

클라이언트 측 Close()를 호출 할 경우는 아무 것도 클라이언트가 더 이상 사용할 수 없도록 닫는, 그것은 문자 그대로 단지 자신을 그것을 닫을 것을 그에게 서버로 전송되지 않습니다. 아직 연결되어 있는지를 확인하는 유일한 방법은 데이터를 보내고 실패를 처리하는 것입니다. 원할 경우 자신의 핸드 셰이크 계약을 구현할 수 있습니다. Close()으로 전화를 걸면 서버에 사실을 알리는 특별한 알림을 보내지 만 해당 패킷이 서버에 도달하지 못할 때가있을 것입니다.

+0

정말 고마워요! 내가해야 할 일은 서버에 단절 메시지를 보내는 것뿐이었습니다. 방법을 호출하고 소켓을 자체적으로 이해하는 것으로 할 수 있다고 생각했지만 삶은 그렇게 쉽지 않습니다. – Bevin

+0

@Bevin, 서버가 연결 해제 메시지를 보내지 않는 연결 해제도 처리하는지 확인하십시오. –

+1

실제로 TCP 연결에 대해 서버가 닫히고 있음을 알리는 내용이 서버에 전송되지 않는다는 진술이 사실입니다. TCP 연결이 정상적으로 종료되면 연결 종료를 시작하려는 측은 FIN 플래그가 설정된 메시지를 보냅니다. 불행히도, NetworkStream 또는 TcpClient 클래스는 기본 소켓 API가 수행하더라도이 문제가 발생했음을 감지하는 방법이 없습니다. 실제로 Chris의 대답은 문제의 올바른 해결책입니다. – reirab

0

1 바이트를 청취하고, 수신하면 나머지를 얻으십시오. 1 바이트 수신시 0이 반환되면 클라이언트 연결이 끊어집니다.

 IPAddress nReceiveAddress = IPAddress.Parse(GetIp(sSource)); 
     IPEndPoint localEndPoint = new IPEndPoint(nReceiveAddress, GetPort(sSource)); 
     Socket nSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     nSocket.Bind(localEndPoint); 

     nSocket.Listen(10); 
     Socket nSocketClient = nSocket.Accept(); 

       byte[] bufferOne = new byte[1]; 
       int nBytes = nClient.Receive(bufferOne); 

       if (nBytes == 0) 
       { 
        AppendToLog(String.Format("{0}: Closing.", sName)); 
        nClient.Close(); 
       } 
       else 
       { 
        byte[] buffer = null; 
        buffer = new byte[nClient.Available + 1]; 

        if (nClient.Available > 0) 
         nBytes = nClient.Receive(buffer); 

        if(nBytes>0) 
        { 
         //KS effectively insert the first received byte at start. 
         Array.Copy(buffer, 0, buffer, 1, buffer.Length - 1); 
         buffer[0] = bufferOne[0]; 
        } 
       } 
관련 문제