套接字关闭可能导致单声道4.0.2

时间:2015-09-20 03:18:23

标签: c# linux sockets mono

最近我发现套接字有问题,导致CLOSE_WAIT,甚至已经关闭并关闭套接字。

  1. 我使用套接字来监听连接,当收到连接时,使用连接接收数据使用BeginReceive,然后接受下一次连接。
  2. 当BeginReceive回调时,使用委托处理数据异步,然后使用BeginReceive,然后关闭并关闭连接。
  3. 客户端连接服务器套接字,然后发送数据,然后在接下来的500~1000ms内关闭套接字。
  4. 重复一段时间,发现很多CLOSE_WAIT连接,但已经调用了shutdown和close。
  5. 控制台输出消息,例如:epoll_ctl(MOD):17文件存在。
  6. 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。

0 个答案:

没有答案