2016-12-23 4 views
1

У меня есть сервер шлюза и 2 клиента. (Сделано в Oracle VM VirtualBox).sleep() в потоке также заставляет основной спать

В моем сервере шлюза у меня есть listener.c прослушивание всех пакетов (в цикле while(1)).

Если клиент отправляет действительный токен, я должен поместить его в список авторизованных MAC-адресов, и все пакеты, исходящие от авторизированных MAC-адресов, должны быть перенаправлены на 180 секунд. (другими словами, данный доступ в Интернет на 180 секунд).

Перед тем, как использовать 180 секунд, предмет с одним пользователем.

/* authorized MACs list */ 
char *auth_macs[5]; 
int client; 
pthread_mutex_t lock; 

/* after 3 min remove the client from auth list */ 
void *timer(void *arg){ 
    sleep(180); 
    pthread_mutex_lock(&lock); 
    auth_macs[client] = " "; 
    client--; 
    pthread_mutex_unlock(&lock); 
    return NULL; 
} 

Вот как я попытался реализовать поток таймера. client - глобальная переменная, которая изменяется в основной функции.

if(has_token == 1){ 
    client++; 
    sprintf(client_ip, "./accept.sh %s", sender); 
    system(client_ip); 
    auth_macs[client] = client_mac; 
    /* start timer thread */ 
    pthread_t tid; 
    pthread_create(&tid, NULL, timer,NULL); 
    pthread_join(tid, NULL); 
} 

Здесь я начинаю эту тему. accept.sh - это сценарий оболочки, разрешающий пересылку.

Моя проблема Я думал, что sleep(180) в потоке таймера только остановится. Но вместо этого listener.c прекращает прием пакетов.

Как это исправить? Я хочу, чтобы таймер ожидал 180 секунд, но все же мог получать пакеты в основной функции.

+4

'pthread_join' будет ждать завершения потока. Как долго он спит. –

ответ

2

sleep() только приостанавливает вызывающую нить. Таким образом, это не влияет на основной поток .

Что проблематична pthread_join() вызов:

pthread_create(&tid, NULL, timer,NULL); 
pthread_join(tid, NULL); 

Это эффективно делает многопоточность бессмысленной. Потому что есть только поток, который когда-либо достигнет прогресса, поскольку основной поток ждет, пока созданный поток не будет завершен.

Вы должны удалить pthread_join() вызов и, возможно, он вне петлю while(1) если основной поток, необходимый для соединения. В качестве альтернативы вы можете вызвать pthread_exit(0) вне цикла создания потоков, так что main завершает выполнение, в то время как остальные потоки, если все еще живы, когда основной поток прерывает свой цикл, может продолжить выполнение.

+1

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

+1

@JohnBollinger Проблема с этой техникой заключается в том, что по мере выхода основного потока она, скорее всего, освободит ресурсы, которые поток демонов все еще использует, вызывая неопределенное поведение в потоке демона. Лучше иметь упорядоченную последовательность выключения. –