释放tcp端口,异步调用

时间:2012-06-07 19:15:34

标签: c# asynchronous port unbind

我有一个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());
            }

        }

    }

}
}

1 个答案:

答案 0 :(得分:0)

几天前我们遇到了这个问题。在我们的例子中,我们必须将Linger模式设置为TRUE(您将其设置为false),超时为0(您已经拥有)。

这有点违反直觉,但确实有效。