Многопоточное выполнение клиент-сервер иногда не заканчивается
Это мой код сервера. Исполняющий босс работник. Я указываю количество рабочих потоков. Проблема в том, что иногда он не отвечает моему клиенту и в основном зависает при получении. Иногда это выполняется, но только если клиентские потоки минимальны. Клиентские потоки иногда не могли подключиться. Может кто-нибудь, пожалуйста, укажите на ошибку. Благодарю.
2 ответа
Контрольно - пропускные пункты:
Как убедиться, что freeThread+1 будет готов к процессу. Не проверяя в своем коде, вы просто пытаетесь заблокировать соответствующий мьютекс.
pthread_mutex_lock(&queue_mutex[freeThread+1]);
Почему вы посылаете сигнал постоянно? Вам не нужно. Только одного раза будет достаточно. Более того, почему вы имеете в виду
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
}
}
}
Это почти все, что вам нужно сделать, чтобы отправить сокеты дочерним потокам.