Многопоточное выполнение клиент-сервер иногда не заканчивается

Это мой код сервера. Исполняющий босс работник. Я указываю количество рабочих потоков. Проблема в том, что иногда он не отвечает моему клиенту и в основном зависает при получении. Иногда это выполняется, но только если клиентские потоки минимальны. Клиентские потоки иногда не могли подключиться. Может кто-нибудь, пожалуйста, укажите на ошибку. Благодарю.

2 ответа

Контрольно - пропускные пункты:

  1. Как убедиться, что freeThread+1 будет готов к процессу. Не проверяя в своем коде, вы просто пытаетесь заблокировать соответствующий мьютекс.

    pthread_mutex_lock(&queue_mutex[freeThread+1]);
    
  2. Почему вы посылаете сигнал постоянно? Вам не нужно. Только одного раза будет достаточно. Более того, почему вы имеете в виду isThreadFree флаг? Это не безопасно с резьбой. В случае состояния гонки, на него будут ошибочно ссылаться. Я думаю, что вы реализуете это с помощью while потому что вы уже столкнулись с этой проблемой.

    while(isThreadFree[freeThread+1]==true) {
      pthread_cond_signal(&queue_has_client[freeThread+1]);
    }
    

Предложение: я не думаю, что вам нужно использовать несколько mutex и cond_signal. Вместо этого вы можете использовать только один мьютекс для очереди clientQueue и конд.

в main() функция:

pthread_mutex_lock(&queue_mutex);
p = enqueue(clientQueue, client_sock);
pthread_mutex_unlock(&queue_mutex);
pthread_cond_signal(&queue_has_client);

в worker() функция:

while (is_empty_queue(clientQueue)) {
  pthread_cond_wait(&queue_has_client,&queue_mutex);
}
dequeue(clientQueue, &helper);
if (!is_empty_queue(clientQueue))
  wake_up_other_thread = true;
pthread_mutex_unlock(&queue_mutex);
if (wake_up_other_thread) // to wake up other threads to serve the enqueued clients
  pthread_cond_signal(&queue_has_client);

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

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

Вот очень простой способ использования трубы в качестве очереди:

static int socketPipe[ 2 ];

void *child_thread( void *arg );
{
    while ( 1 ) {
        int mySocket;
        size_t bytesRead = read( socketPipe[ 0 ], &mySocket, sizeof( mySocket ) );
        if ( bytesRead != sizeof( mySocket ) ) {
            // error
        }
        // now handle socket connection in mySocket
    }
    return( NULL );
}

int main( int argc, char **argv )
{
    // create socket pipe
    int rc = pipe( socketPipe );

    // create threads and listener socket

    // handle incoming connections and pass to child threads
    while ( 1 ) {
        int newConn = accept( mainSocket, &peer, &lenPeer )
        if ( incomingConnection != -1 ) {
            ssize_t written =
                write( socketPipe[ 1 ], &newConn , sizeof( newConn ) );
            // handle errors
        }
    }
}

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

Другие вопросы по тегам