2017-11-28 23 views
0

ソケットクライアント/サーバーを使用していくつかの問題が発生しています。クライアント側のソケットを閉じる原因TIME_WAIT保留状態

private static void Send(Socket handler, String data) 
{ 
    try 
    { 
     // Convert the string data to byte data using ASCII encoding. 
     byte[] byteData = Encoding.ASCII.GetBytes(data); 

     // Begin sending the data to the remote device. 
     handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); 
    } 
    catch { } 
} 

private static void SendCallback(IAsyncResult ar) 
{ 
    try 
    { 
     // Retrieve the socket from the state object. 
     Socket handler = (Socket)ar.AsyncState; 

     // Complete sending the data to the remote device. 
     int bytesSent = handler.EndSend(ar); 
     Console.WriteLine("Sent {0} bytes to client.", bytesSent); 

     handler.Shutdown(SocketShutdown.Both); 
     //handler.Dispose(); 
     handler.Close(); 



    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

が、私は近いソケット関数を呼び出す、私は、サーバーからの回答を読んだ後:私は応答を送信した後、私のソケットの流れで

は、私は、サーバー側で閉じ

var cc = new AsynchronousClient("192.168.1.201", 11001); 
var er = cc.echo(); 
cc.closeConn(); 

public void closeConn(){ 
    sc.Close(); 
} 

public void Close() 
{ 
    if (socket != null && IsConnected) 
    { 
     OnClosed(this, EventArgs.Empty); 
     IsConnected = false; 

     socket.Close(); 
     socket = null; 
    } 
} 

呼び出しがサーバー側とクライアント側の両方で呼び出された後、TCPViewを使用して、ポートがTIME_WAIT状態にあることがわかります。 Dispose、Disconnect、その他の高速な解決策などのメソッドを使用するような他のソリューションを試しましたが、通信の終了時に強制的に接続を閉じてポートを解放するものはありません。

この画像を見ると、TIME_WAITがソケットの実際の閉じ前の最後の状態であることがわかります。

私はまた、接続だけのサーバー側を閉じるなども試みました。私が得るのは、クライアントがCLOSE_WAIT状態でブロックされ、サーバーがFIN_WAIT2状態でブロックされることです。したがって、TIME_WAITの前のステップ。

何らかの形で、私は最後のACKをTIME_WAITからCLOSEDに渡す必要があると思います。どのように私の目標に達することができますか?

enter image description here

UPDATE

私は、サーバー側でこれを試してみました:

var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

// Bind the socket to the local endpoint and listen for incoming connections. 
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
listener.Bind(localEndPoint); 
listener.Listen(100); 
+1

あなたの目標は何ですか? 'TIME_WAIT'を避ける?いいえ、できません。その効果を最小限にするには 'so_reuseaddr'を使います。 –

+0

@ZangMingJieはい、私の目標はTIME_WAITを避けています。私はできません?更新を見て、私はreuseaddressオプションを試しましたが、私は変更に気付かなかった。多分私はそれを間違った方法で設定したのでしょうか? –

+0

は問題を引き起こしている 'TIME_WAIT'ですか?もしそうでなければ、誰が気にしますか?あなたはそれを避けることはできません、無視してください。 –

答えて

0

ソリューションは、WindowsのAPIを使用しています。ここで

コード:

[DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
public static extern int closesocket(IntPtr s); 

、コールは、私は両方ではない、片側のみでこれを呼び出す

closesocket(socket.Handle); 

です。 TCPViewの長い分析の後、私はそれが期待どおりに動作すると言うことができます。

関連する問題