断开连接后再次使用Socket进行监听

时间:2010-11-30 04:51:23

标签: c# sockets asynchronous

我正在编写一个小型的C#套接字应用程序。实际上我有两个,一个服务器和一个客户端。

用户运行客户端,输入服务器的IP和端口,按“连接”,然后连接后,他们可以将文本输入文本框并将其发送到服务器。

服务器只显示“无连接”或“来自[ip]:[端口]的连接”,以及最近收到的消息。

服务器成功接收消息,甚至可以正常处理客户端断开连接。 现在我试图让它在客户端断开连接后再次监听但由于某种原因,我尝试不允许它再次开始监听。

以下是我的代码的一部分:

    Socket socket;
    private void listen()
    {
        socket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
        socket.Bind(new IPEndPoint(IPAddress.Any, 12345));
        socket.Listen(10);
        socket.BeginAccept(new AsyncCallback(acceptAsync), socket);
    }

    private void receiveAsync(IAsyncResult res)
    {
        Socket socket = (Socket)res.AsyncState;

        try
        {
            int nBytes = socket.EndReceive(res);
            if (nBytes > 0)
            {
                Invoke(new MethodInvoker(delegate()
                {
                    lMessage.Text = encoder.GetString(buffer);
                }));
                setupReceiveAsync(socket);
            }
            else
            {
                Invoke(new MethodInvoker(delegate()
                {
                    lConnections.Text = "No Connections.";
                    lMessage.Text = "No Messages.";
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();
                    listen();
                }));
            }
        }
        catch { }
    }

最后一行:listen();是什么引发了错误。 我试过再次调用socket.BeginAccept(),但这也会引发异常。

我得到的信息是:

  

通常只允许使用每个套接字地址(协议/网络地址/端口)

如果我不调用我的listen()函数而只是调用socket.BeginAccept(),那么我得到“你必须先调用socket.listen()”

如果我调用了socket.listen()函数,那么它会告诉我它已经连接并且购物车开始聆听。

一旦我进行了异步连接,并收到了几条异步消息,我该如何再次开始接收?

2 个答案:

答案 0 :(得分:2)

第二次调用socket时,您的listen()变量已经分配了一个侦听套接字,这就是为什么它只允许您使用一个用法。您需要重复的只是socket.BeginAccept(new AsyncCallback(acceptAsync), socket)电话。因此,请尝试使用listen()替换receiveAsync(...)方法中的socket.BeginAccept(new AsyncCallback(acceptAsync), socket)来电。

答案 1 :(得分:2)

async Begin*后面始终跟End*。请参阅使用Asynchronous Server Socket。你的接受方法应该是这样的:

try {
        listener.Bind(localEP);
        listener.Listen(10);

        while (true) {
            allDone.Reset();

            Console.WriteLine("Waiting for a connection...");
            listener.BeginAccept(
                new AsyncCallback(SocketListener.acceptCallback), 
                listener );

            allDone.WaitOne();
        }
    } catch (Exception e) {

服务器,表示侦听指定端口/ IP的应用程序。通常,总是处于监听模式 - 这就是它被称为服务器的原因。它可以连接断开客户端,但始终处于监听模式。

这意味着,当服务器断开客户端 - 甚至时 - 它处于监听模式;这意味着它也可以接受传入的连接。

但是,断开连接请求可以来自客户端,也可以由服务器强制应用。

服务器的过程是:

  1. 绑定到套接字
  2. 收听
  3. 接受连接
  4. 客户的流程是:

    1. 连接到服务器
    2. 发送/接收消息
    3. 服务器可以通过多种方式处理传入的客户端,如下所示:

      • 传入连接在列表中维护,例如在List<TcpClient>
      • 处理传入客户端的一种方法是通过线程。例如,对于每个传入的客户端,产生一个线程来处理服务器和客户端之间的通信。例如,checkout this example

      _

      private  void ListenForClients()
      {
        this.tcpListener.Start();
      
        while (true)
        {
          //blocks until a client has connected to the server
          TcpClient client = this.tcpListener.AcceptTcpClient();
      
          //create a thread to handle communication
          //with connected client
          Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
          clientThread.Start(client);
        }
      }
      
      • 使用单线程并使用上下文切换来管理客户端通信(TX / RX)。