C # асинхронный сервер с использованием делегатов для BeginInvoke - PullRequest
2 голосов
/ 27 марта 2012

Итак, я попробовал следующую программу, чтобы сделать асинхронный сервер, когда его синхронизация проста, и я могу говорить только с сервером с 1 соединением, потому что второе не разрешено.Я делаю класс Server.cs с моей серверной реализацией.Для клиники я использую 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 ]

1 голос
/ 27 марта 2012

Разве не должно быть другого числа, такого как нить 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);
    }
0 голосов
/ 27 марта 2012

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

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

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

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

...