2012-06-07 4 views
0

У меня есть TCP-сервер, который постоянно получает потоки tcp из разных источников. У меня есть внешнее событие, которое вызывает остановку, и когда это произойдет, порт TCP должен быть выпущен. Приведенный ниже код работает правильно, за исключением закрытия. Закрытие не освобождает порт, а порт tcp застрял в состоянии прослушивания. любая помощь будет действительно велика. Спасибо.Освобождение порта tcp, асинхронный вызов

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading; 
using System.Windows.Forms; 


namespace TestTest 
{ 

public class tcpserver 
{ 

    //State object for reading client data asynchronously 
    public class StateObject 
    { 
     // Client socket. 
     public Socket workSocket = null; 
     // Size of receive buffer. 
     public const int BufferSize = 2097152; 
     // Receive buffer. 
     public byte[] buffer = new byte[BufferSize]; 
     // Received data string. 
     public StringBuilder sb = new StringBuilder(); 

    } 

    public class AsynchronousSocketListener 
    { 
     public Form10 m_parent; 
     Socket parentlistener;   

     // Incoming data from client. 
     public static string data = null; 

     // Thread signal. 
     public static ManualResetEvent allDone = new ManualResetEvent(false); 

     public AsynchronousSocketListener() 
     { 
     } 

     public void StartListening(Form10 frm10) 
     { 
      m_parent = frm10; 

      try 
      { 
      // Data buffer for incoming data. 
      byte[] bytes = new Byte[2097152]; 
      int port = Convert.ToInt32(m_parent.textBox2.Text.Trim()); 
      IPAddress ipv4 = IPAddress.Parse(m_parent.comboBox1.SelectedItem.ToString().Trim()); 
      IPEndPoint localEndPoint = new IPEndPoint(ipv4, port); 
      // Create a TCP/IP socket.      
      parentlistener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      parentlistener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, false); 
      LingerOption lo = new LingerOption(false, 0); 
      parentlistener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo); 
      //setting the array to have this ip and port      
      m_parent.m_parent.setUsedIPport(m_parent.comboBox1.SelectedItem.ToString().Trim() + ":" + m_parent.textBox2.Text.Trim()); 


       // Bind the socket to the local endpoint and listen for incoming connections. 

       try 
       { 
        parentlistener.Bind(localEndPoint);    // THIS IS THE PORT I WOULD LIKE TO RELEASE ON AN EXTERNAL TRIGGER 
        parentlistener.Listen(100); 

        while (m_parent.getStopState() == false) 
        { 
        // MessageBox.Show("L"); 

         allDone.Reset(); 

         //// Start an asynchronous socket to listen for connections. 
         parentlistener.BeginAccept(new AsyncCallback(AcceptCallback), parentlistener); 

        } 

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


      } 
      catch (Exception) { MessageBox.Show("Error binding to tcp port", "ERROR"); return; } 


     } 

     public void AcceptCallback(IAsyncResult ar) 
     { 
      try 
      { 
       // Signal the main thread to continue. 
       allDone.Set(); 

       // Get the socket that handles the client request. 
       Socket listener = (Socket)ar.AsyncState; 
       Socket handler = listener.EndAccept(ar); 
       LingerOption lo = new LingerOption(false, 0); 
       handler.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);      

       // Create the state object. 
       StateObject state = new StateObject(); 
       state.workSocket = handler; 


       handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 

      } 
      catch (Exception er) { //MessageBox.Show(er.ToString()); 
      } 
     } 

     public void ReadCallback(IAsyncResult ar) 
     { 

      try 
      { 


       String line = String.Empty; 
       // Retrieve the state object and the handler socket 
       // from the asynchronous state object. 
       StateObject state = (StateObject)ar.AsyncState; 
       Socket handler = state.workSocket; 

       string temporaryString = ""; 
       // Read data from the client socket. 
       int bytesRead = handler.EndReceive(ar); 

       if (bytesRead > 0) 
       { 
        // There might be more data, so store the data received so far. 
        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 

        line = state.sb.ToString(); //this goes into an external store, code is not here 

        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 

        } 
       } 

      } 
      catch (Exception er) { //MessageBox.Show(er.ToString()); 
      } 
     } 

     public void stopListener() 
     { 

      try 
      {     


       parentlistener.Shutdown(SocketShutdown.Both); 
       //parentlistener.Disconnect(true); 
       parentlistener.Close();       //PROBLEM !!! code is not releasing the port, the tcp port continues to remain in the listening state. 
       parentlistener.Dispose(); 
      } 
      catch (Exception Ex) { //MessageBox.Show(Ex.ToString()); 
      } 

     } 

    } 

} 
} 

ответ

0

У нас была эта точная проблема всего несколько дней назад. В нашем случае мы должны были установить для режима Linger значение TRUE (у вас установлено значение false) с таймаутом 0 (который у вас уже есть).

Это немного контр-интуитивно понятное, но оно сработало.