Может ли мой рутинный сервер работать нормально? - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь построить несколько клиентов - одну структуру сервера. Каждый клиент устанавливает соединение с сервером, и сервер поддерживает это соединение.

Клиент имеет два потока (thread1, thread2), работающих асинхронно и совместно использующих 1 сокет для отправки, получения. Два потока каждый содержит несколько функций отправки, получения. Чтобы сервер обслуживал каждого клиента, он также должен создать два клиентских обработчика с одним сокетом.

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

Вот моя предполагаемая реализация подпрограммы выбора на стороне сервера с использованием кода, близкого к c #.

server.selectRoutine(){

while(!serverSocket.closed())
{
    checkReadList client_connect_socket_list_copy=new ArrayList<Socket>(client_connect_socket_list) ;
    Socket.Select(client_connect_socket_list_copy, null,null) ;

    foreach(Socket s in client_connect_socket_list_copy)
    {
        client_connect_info info=client_connect_info_dict.Items[s] ;

        if(!info.is_client_thread1_handler_active)
        {
            info.is_client_thread1_active=true ;
            clServerEntranceHandler handler=new clServerEntranceHandler() ;

            Task.Run(handler.run()) ;
        }

        if(!info.is_client_thread2_handler_active)
        {
            info.is_client_thread2_active=true ;

            clServerExitHandler handler=new clServerExitHandler() ;

            Task.Run(handler.run()) ;
        }           
}

Код Объяснение

  • Client_connect_socket_list: содержит подключенных в данный момент клиентов
  • client_connect_info_dict: клиентский информационный словарь подключения, сопоставленный для каждого сокета в качестве ключа.
  • client_connect_info: состоит из (is_client_thread1_Handler_Active, is_client_thread2_Handler_Active)
  • Выберите только те сокеты, которые готовы для чтения после Socket.Select
  • Запустить обработчик для тех сокетов, где обработчик в данный момент не создан, info.is_client_thread1_Handler_Active=false. И установить info.is_client_thread1_Handler_Active=true. Это связано с тем, что внутри уже созданного обработчика будет несколько recv функций, и они будут в режиме блокировки. Поэтому, когда клиент отправляет сообщение на сервер, предназначенный для функции recv, заблокированной в уже созданном обработчике, Socket.Select также будет считать этот сокет готовым для чтения и в итоге создаст новый обработчик. Чтобы избежать этого, мне нужно проверить, активен ли обработчик. После того, как обработчик завершит работу, он установит info.is_client_thread1_Handler_Active= false внутри. То же самое для обработчика client_thread2.

Я думаю, что теперь мне нужно синхронизировать эту процедуру с каждым уже созданным обработчиком. Например, избегайте ситуации, подобной функции recv внутри обработчика P рывка сообщения A внутри очереди сообщений сокета обработчика P после Socket.Select пильного сообщения A внутри очереди сообщений. Затем обработчик P завершится и установит info.is_Handler_Active=false. Затем selectRoutine снова создаст новый обработчик для сообщения A, уже прочитанного обработчиком P, и возникнет проблема.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...