Чат-сервер с большим количеством клиентов - PullRequest
1 голос
/ 23 февраля 2010

Я прочитал некоторый исходный код чата C # и вижу: на сервере чата с большим количеством подключенных клиентов прослушиватель сервера будет работать в отдельном потоке, а каждый подключенный клиент также будет работать в отдельном потоке. Примеры кода:

Запустите сервер и начните прослушивание в отдельном потоке:

    public void StartListening()
        {

            // Get the IP of the first network device, however this can prove unreliable on certain configurations
            IPAddress ipaLocal = ipAddress;

            // Create the TCP listener object using the IP of the server and the specified port
            tlsClient = new TcpListener(1986);

            // Start the TCP listener and listen for connections
            tlsClient.Start();

            // The while loop will check for true in this before checking for connections
            ServRunning = true;

            // Start the new tread that hosts the listener
            thrListener = new Thread(KeepListening);
            thrListener.Start();
        }

private void KeepListening()
        {
            // While the server is running
            while (ServRunning == true)
            {
                // Accept a pending connection
                tcpClient = tlsClient.AcceptTcpClient();
                // Create a new instance of Connection
                Connection newConnection = new Connection(tcpClient);
            }
        }

И соединение также будет выполняться в отдельном потоке:

public Connection(TcpClient tcpCon)
        {
            tcpClient = tcpCon;
            // The thread that accepts the client and awaits messages
            thrSender = new Thread(AcceptClient);
            // The thread calls the AcceptClient() method
            thrSender.Start();
        }

Таким образом, если сервер чата с 10000 подключенными клиентами, приложение сервера чата будет иметь 10002 потока (один основной поток, один поток сервера и 10000 потоков клиента). Я думаю, что сервер чата будет перегружен большим количеством потоков. Пожалуйста, помогите мне решение. Спасибо.

UPDATE: Я считаю, что примеры в чате предназначены только для изучения сетей, и они не подходят для реальной модели. Пожалуйста, дайте мне реальное решение. Спасибо.

Ответы [ 5 ]

1 голос
/ 23 февраля 2010

Если вы используете .Net framework 2.0 SP2 или выше, вы можете использовать новую модель асинхронных сокетов, основанную на IO Completion ports . В этом случае вы не должны создавать свои собственные потоки, потому что порты завершения ввода-вывода делают всю работу за вас.

Вот несколько примеров:

tcpServer = new System.Net.Sockets.TcpListener(IPAddress.Any, port);
tcpServer.Start();
tcpServer.BeginAcceptSocket(EndAcceptSocket, tcpServer);


private void EndAcceptSocket(IAsyncResult asyncResult)
{
    TcpListener lister = (TcpListener)asyncResult.AsyncState;
    Socket sock = lister.EndAcceptSocket(asyncResult);
    //handle socket connection (you may add socket to you internal storage or something)

    //start accepting another sockets
    lister.BeginAcceptSocket(EndAcceptSocket, lister);


    SocketAsyncEventArgs e = new SocketAsyncEventArgs();
    e.Completed += ReceiveCompleted;
    e.SetBuffer(new byte[socketBufferSize], 0, socketBufferSize);
    sock.ReceiveAsync(e);
}


void ReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
    var sock = (Socket)sender;
    if (!sock.Connected)
    {
      //handle socket disconnection
    }
    var buf = new byte[size];
    Array.Copy(e.Buffer, buf, size);
    //handle received data

    //start reading new data
    sock.ReceiveAsync(e);
}
1 голос
/ 23 февраля 2010

Стандартный механизм для облегчения нагрузки известен как выбор, который может мультиплексировать несколько экземпляров Socket для наблюдения за теми, которые готовы для чтения или записи. См. Этот документ: http://codeidol.com/csharp/csharp-network/Csharp-Network-Programming-Classes/Csharp-Socket-Programming/ и прокрутите вниз до раздела select ().

0 голосов
/ 10 июня 2012

Предлагаю вам прочитать эту замечательную статью на MSDN Magazine. Описание:

  • Сервер с резьбой
  • Выбор на основе сервера
  • Асинхронный сервер

коды в C # & VB.Net

0 голосов
/ 23 февраля 2010

1) Вы НИКОГДА не захотите, чтобы работало столько потоков - даже если бы вы могли заставить их работать на вашем компьютере (чего вы не можете - каждый поток имеет связанный с ним стек, который занимает реальную память и, как только вы запускаете больше и все больше и больше у вас кончатся физические ресурсы в вашем ящике и вы увидите, как он взрывается).

2) Вы захотите изучить пул потоков - используя меньшее количество потоков для выполнения большего объема работы - как правило, читая из очереди работы, которую вы пытаетесь пройти как можно быстрее.

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

4) Что происходит, когда вы масштабируете за пределы одной машины? Что вы надеетесь сделать, если вы успешны, верно? :-) Обычно люди выделяют для беседы набор из N машин - затем они хэшируют на основе идентификатора пользователя (например, GUID, представляющий пользователя) или UserID / bigint в зависимости от того, что соответствует некоторому внутреннему токену аутентификации, который является непротиворечивым от входа в систему до входа в систему), что позволяет им детерминистически направлять информацию о состоянии / состоянии пользователя на конкретную машину в этом наборе из N блоков, предназначенных для обмена сообщениями. Таким образом, если пользователю, который хэширует сервер N [2], необходимо проверить, вошли ли их друзья, легко узнать для каждого из своих друзей, на какой именно машине должен находиться статус их друга, потому что серверная часть постоянно хэширует этих друзей в IM. машина, которая соответствует каждому хешу идентификатора пользователя. (т. е. вы просто знаете из ИД пользователя, какой сервер в ферме должен обрабатывать состояние IM для этого пользователя.

Только не думай, что ты раскручиваешь кучу ниток, и это спасет день. Это небрежно и работает только в очень небольших количествах.

0 голосов
/ 23 февраля 2010

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

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

...