0

我有一个 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, and 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 !!! The 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());
                }
            }
        }
    }
}
4

1 回答 1

0

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

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

于 2012-06-08T02:58:00.793 回答