最近我在socket中发现了一个问题,导致CLOSE_WAIT,甚至已经关闭并关闭套接字 .
-
我使用套接字来监听连接,当收到连接时,使用连接接收数据使用BeginReceive,然后接受下一次连接 .
-
当BeginReceive回调时,使用委托处理数据异步,然后使用BeginReceive接下来,然后关闭并关闭连接 .
-
客户端连接服务器套接字,然后发送数据,然后在接下来的500~1000ms内关闭套接字 .
-
重复一段时间,发现了很多CLOSE_WAIT连接,但已经调用了shutdown和close .
-
控制台输出消息如:epoll_ctl(MOD):17文件存在 .
CentOS 6.2 x64单声道4.0.2
是否有一些身体遇到同样的情况?或者给我一些建议 . 非常感谢 .
示例代码:
public class SocketTest
{
private const int NET_LISTEN_BACKLOG = 128;
private Socket m_serverSocket = null;
private Thread m_mainThread = null;
public int m_acceptNum = 0;
public SocketTest( )
{
m_mainThread = new Thread( new ThreadStart( MainProc ) );
m_mainThread.Start( );
}
public void Startup( int port )
{
m_serverSocket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
m_serverSocket.Bind( new IPEndPoint( IPAddress.Any, port ) );
m_serverSocket.Listen( NET_LISTEN_BACKLOG );
m_serverSocket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true );
m_serverSocket.BeginAccept( new AsyncCallback( ServerAcceptCallback ), null );
}
private void ServerAcceptCallback( IAsyncResult ar )
{
try
{
//debug
Interlocked.Increment( ref m_acceptNum );
Socket socket = m_serverSocket.EndAccept( ar );
socket.NoDelay = true;
STcpConnection con = new STcpConnection( socket );
con.RecvPakAsync( new SPackRecvCallback( TestProtocolPackRecvCallback ), null );
m_serverSocket.BeginAccept( new AsyncCallback( ServerAcceptCallback ), null );
}
catch( Exception ex )
{
Console.WriteLine( "ServerAcceptCallback : " + ex.ToString( ) );
}
}
delegate void STestSendPackDelegate( STcpConnection conn );
private void TestProtocolPackRecvCallback( STcpConnection conn, bool success, byte[] packData, string errMsg, object state )
{
try
{
if( !success )
{
conn.Close( );
return;
}
STestSendPackDelegate dele = new STestSendPackDelegate( RetPack );
dele.BeginInvoke( conn, null, null );
conn.RecvPakAsync( new SPackRecvCallback( TestProtocolPackRecvCallback ), null );
//here if close the socket, will cause CLOSE_WAIT.
conn.Close( );
}
catch( Exception ex )
{
Console.WriteLine( "TestProtocolPackRecvCallback : " + ex.ToString( ) );
}
}
private void RetPack( STcpConnection conn )
{
byte[] data = Encoding.ASCII.GetBytes( "Hello" );
conn.TrySendDataAsync( data );
}
private void MainProc( )
{
try
{
while( true )
{
Console.WriteLine( string.Format( "-------------------------- {0} ---------------------------", DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss" ) ) );
Console.WriteLine( "m_acceptNum : " + m_acceptNum );
Thread.Sleep( 5000 );
}
}
catch( Exception ex )
{
Console.WriteLine( ex.ToString( ) );
}
}
}
public delegate void SPackRecvCallback( STcpConnection conn, bool success, byte[] packData, string errMsg, object state );
public class STcpConnection
{
private Socket m_socket = null;
public IPAddress IPAddress
{
get { return ( ( IPEndPoint )m_socket.RemoteEndPoint ).Address; }
}
public int Port
{
get { return ( ( IPEndPoint )m_socket.RemoteEndPoint ).Port; }
}
public STcpConnection( Socket socket )
{
if( socket == null )
throw new ArgumentNullException( );
m_socket = socket;
}
......
public void Close( )
{
try
{
try
{
m_socket.Shutdown( SocketShutdown.Both );
}
catch( Exception ex )
{
Console.WriteLine( "Close Exception : " + ex.ToString( ) );
}
m_socket.Close( );
}
}
catch( Exception ex )
{
Console.WriteLine( ex.ToString( ) );
}
}
private void OnPakRecvCallback( SPackRecvCallback cb, object state, bool success, byte[] msg, string errMsg )
{
try
{
if( cb != null )
{
cb( this, success, msg, errMsg, state );
}
}
catch( Exception ex )
{
Console.WriteLine( ex.ToString( ) );
}
}
}
问题出现在实际项目中,代码是重现问题的核心 . 在项目中我们没有这么近,但在某些情况下会有CLOSE_WAIT .