使用BeginInvoke委托的C#异步服务器

时间:2012-03-27 15:51:19

标签: c# sockets delegates asyncsocket

所以我尝试使用以下程序制作异步服务器,当它同步时很简单,我只能通过1连接与服务器通话,因为第二个不允许。我用我的服务器实现创建了一个Server.cs类。对于clinet我使用Microsoft Telnet。

的Program.cs:

static void Main(string[] args)
    {
        Server myServer = new Server();
        myServer.StartListening();
        Console.ReadKey();
    }

Server.cs

class Server
{
    //Delegates
    delegate void socketConnection();
    socketConnection myConnection;

    //Needed for connections
    public IPEndPoint serverIPEP { get; set; }
    public Socket serverSocket { get; set; }
    public int numberOfConnections { get; set; }
    public List<Socket> activeConnections;

    //Constructors
    public Server()
    {
        serverIPEP = new IPEndPoint(IPAddress.Any, 9080);
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        numberOfConnections = 10;
        activeConnections = new List<Socket>(numberOfConnections);
    }

    public Server(IPEndPoint serverIPEP)
    {
        this.serverIPEP = serverIPEP;
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        numberOfConnections = 10;
        activeConnections = new List<Socket>(numberOfConnections);
    }

    public Server(Socket serverSocket)
    {
        serverIPEP = new IPEndPoint(IPAddress.Any, 9080);
        this.serverSocket = serverSocket;
        numberOfConnections = 10;
        activeConnections = new List<Socket>(numberOfConnections);
    }

    public Server(IPEndPoint serverIPEP, Socket serverSocket, int numberOfConnections)
    {
        this.serverIPEP = serverIPEP;
        this.serverSocket = serverSocket;
        this.numberOfConnections = numberOfConnections;
        activeConnections = new List<Socket>(numberOfConnections);
    }

    public void StartListening()
    {
        serverSocket.Bind(serverIPEP);
        serverSocket.Listen(numberOfConnections);

        Console.WriteLine("Waiting for connections...");

        //Here I made a loop with the callback :) I don't think its the cleverest implementation
        myConnection = new socketConnection(GetConnections);
        IAsyncResult connectionResult = myConnection.BeginInvoke(callBack, this);

        //connectionResult.AsyncWaitHandle.WaitOne();
    }

    private void GetConnections()
    {
        Socket clientSocket = serverSocket.Accept();
        activeConnections.Add(clientSocket);
    }

    private void callBack(IAsyncResult itfAR)
    {
        Console.WriteLine("Current thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        myConnection.BeginInvoke(callBack, this);
    }

问题是,当我连接2个客户端时,它告诉我它们在同一个线程上,我希望它们在分离的线程上。它告诉我:

Waiting for connections...
Current thread: 7
Current thread: 7

不应该有另一个数字,如线程7,然后是第9个线程?或者它是这样发生的,因为我从同一台计算机连接到服务器?

2 个答案:

答案 0 :(得分:1)

  

不应该有另一个数字,如线程7,然后是第9个线程?或者它是这样发生的,因为我从同一台计算机连接到服务器?

Delegate.BeginInvoke从线程池中获取一个线程。您看到相同线程ID的原因是因为该线程处于空闲状态。如果线程忙,那么BeginInvoke将获取一些其他线程。例如:

 private void callBack(IAsyncResult itfAR)
    {
        Console.WriteLine("Current thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
        myConnection.BeginInvoke(callBack, this);
        Thread.Sleep(100000);
    }

答案 1 :(得分:0)

在您的代码中有一些不太正确的事情。你永远不会在原始套接字上结束接受,所以我认为,因为你的客户端都来自同一个地址,你只是向原始的listen调用发送一个恒定的数据流(我可能在这个特定的细节上错了,就像我没有真正完整地跟踪你的代码。)

在你的回调中,你希望在获得发送它的任何数据后结束第一个连接,然后产生一个新连接。此外,您希望将StartListening()方法封装在循环中,并在完成连接时设置事件处理程序。

在MSDN站点上有一个非常好的异步套接字侦听器示例。我使用修改后的版本来满足我的目的,但原则是坚实的。

Using an Asynchronous Server Socket