【问题标题】:How do I Listen Over a Socket for Incoming Connections After the Last Connection is Closed?最后一个连接关闭后,如何通过套接字侦听传入连接?
【发布时间】:2013-02-15 00:33:29
【问题描述】:

我正在设置一个套接字来监听传入的连接:

public Socket Handler;

public void StartListening()
{
    // Establish the locel endpoint for the socket
    IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Port);

    // Create a TCP/IP socket
    Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    try
    {
        // Bind the socket to the local endpoint and listen
        listener.Blocking = false;
        listener.Bind(localEndPoint);
        listener.Listen(100);

        // Start an asynchronous socket to listen for connections
        listener.BeginAccept( new AsyncCallback(AcceptCallback), listener);
    }
    catch (Exception e)
    {
        invokeStatusUpdate(0, e.Message);
    }            
}

private void AcceptCallback(IAsyncResult ar)
{
    // Get the socket that handles the client request
    Socket listener = (Socket) ar.AsyncState;
    Socket handler = listener.EndAccept(ar);
    Handler = handler;

    // Create the state object
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}

正如您在上面看到的,一旦建立连接,我就会设置我的 BeginReceive 回调。这很好用。

最终我想关闭当前连接,然后再次开始在我的套接字上监听传入连接尝试:

public void CloseNode(bool restart)
{
    try
    {
        if (Handler != null)
        {
            Handler.Shutdown(SocketShutdown.Both);
            Handler.Close();
            Handler.Dispose();
            Handler = null;
        }

        if (restart)
            StartListening();
    }
    catch (Exception e)
    {
        invokeStatusUpdate(0, e.Message);
    }
}

我的 close 方法需要一个布尔值来判断它是否应该开始监听更多的传入连接。

问题是当我回到我的StartListening 方法时,我在listener.Bind(localEndPoint); 行上得到一个异常,说“每个套接字地址(协议/网络地址/端口)只有一种用法是通常允许”

如何设置我的收听以重新开始收听?

【问题讨论】:

    标签: c# sockets listener


    【解决方案1】:

    分为两种方法:startListening()continueListening()

    开始收听将初始化所有内容,然后调用继续收听。现在在你呼叫的地方开始收听,改为继续收听。

    或者,如果您想一次允许多个,只需将 BeginAccept 调用放入 while(true) 循环中。这将永远接受所有传入的连接,即使其他人已经连接。这就是为什么它毕竟是异步的!

    这是你的成员变量

    public Socket Handler;
    private socket listener; // added by corsiKa
    

    这是你的新开始方法

    public void StartListening()
    {
        // Establish the locel endpoint for the socket
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Port);
    
        // Create a TCP/IP socket
        listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
        try
        {
            // Bind the socket to the local endpoint and listen
            listener.Blocking = false;
            listener.Bind(localEndPoint);
            listener.Listen(100);
    
            // Start an asynchronous socket to listen for connections
            performListen(listener); // changed by corsiKa
        }
        catch (Exception e)
        {
            invokeStatusUpdate(0, e.Message);
        }            
    }
    

    这是你的执行监听方法

    // added by corsiKa
    private void performListen(Socket listener) {
        listener.BeginAccept( new AsyncCallback(AcceptCallback), listener);
    }
    

    这是您的新关闭方法

    // variable name changed by corsiKa
    public void CloseNode(bool acceptMoreConnections)
    {
        try
        {
            if (Handler != null)
            {
                Handler.Shutdown(SocketShutdown.Both);
                Handler.Close();
                Handler.Dispose();
                Handler = null;
            }
            // changed by corsiKa
            if (acceptMoreConnections)
                performListen(listener);
        }
        catch (Exception e)
        {
            invokeStatusUpdate(0, e.Message);
        }
    }
    

    【讨论】:

    • 我一次只想要一个连接。我不确定我会在哪里拆分方法来执行您的建议。我是否应该将该套接字设为全局并让ContinueListening 方法简单地调用BeginAccept
    • 您实际上可以将您的 if(restart) startListening(); 替换为 if(restart) listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); 显然这需要提供对套接字的访问权限。
    • 添加了代码。我不是 C# 人,我是 Java 人。所以有些语法可能是错误的。但我想有一个问题很容易解决。
    • 这很好用。感谢您的帮助。如果你不介意,你能解释一下为什么这里实现了两个套接字吗?在侦听器和处理程序之间,我对它们的角色有点困惑。
    • 我不知道你的 Handler 套接字是做什么的。我完全忽略了它。
    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多