Асинхронный сервер С#, использующий делегаты для BeginInvoke

Итак, я попробовал следующую программу для создания асинхронного сервера, когда его синхронизация проста, и я могу говорить с сервером только с 1 соединением, потому что второе не разрешено. Я создаю класс Server.cs с моей реализацией сервера. Для клиента я использую Microsoft Telnet.

Программа.cs:

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

Сервер.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);
    }

Проблема в том, что когда я подключаюсь к двум клиентам, мне говорят, что они находятся в одном потоке, и я хочу, чтобы они были в разных потоках. Он говорит мне:

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

Разве не должен быть другой номер, например, поток 7, а затем поток 9? Или это происходит потому, что я подключаюсь к серверу с того же компьютера?


person Thanatos    schedule 27.03.2012    source источник


Ответы (2)


Разве не должен быть другой номер, например, поток 7, а затем поток 9? Или это происходит потому, что я подключаюсь к серверу с того же компьютера?

Delegate.BeginInvoke захватывает поток из пула потоков. Причина, по которой вы видите тот же идентификатор потока, заключается в том, что этот поток простаивает. Если поток был занят, то BeginInvoke захватит другой поток. Например:

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

Есть несколько вещей, которые не совсем верны в вашем коде. Вы никогда не завершаете прием в исходном сокете, поэтому я думаю, что, поскольку ваши клиенты оба с одного и того же адреса, вы просто отправляете постоянный поток данных исходному вызову прослушивания (я могу ошибаться в этой конкретной детали, так как Я действительно не очень тщательно проследил ваш код).

В своем обратном вызове вы хотите завершить первое соединение после получения любых отправленных им данных, а затем создать новое. Кроме того, вы хотите инкапсулировать свой метод StartListening() в цикле и установить обработчик событий, когда вы завершите соединение.

На сайте MSDN есть довольно хороший пример прослушивателя асинхронных сокетов. Я использую модифицированную версию для своих целей, но принцип верен.

Использование асинхронного серверного сокета

person Sean H    schedule 27.03.2012