最近我发现套接字有问题,导致CLOSE_WAIT,甚至已经关闭并关闭套接字。
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。