Остановить сервер-> как проверить, остановлен ли поток -> pthread

0

Основная задача → STOP Server, как только клиент отключится.

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

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

Теперь моя следующая цель - выяснить, завершился ли отсоединенный поток, и если да, то закройте "accept socket" (из ниже кода его nsk-переменная). Чтобы достичь этого, как я узнаю, что отдельный процесс завершен? У меня не было много информации из сети. во-вторых, кто-то предложил использовать pthreadkill, но для этого, как я могу найти pid?

Может кто-то может меня выручить.
благодаря

   static int sco_listen()
{
printf(" we are in sco_listen_function\n" );
    struct sockaddr_sco addr;
    struct sco_conninfo conn;
    socklen_t optlen;
    int sk, nsk;
    char ba[18];
    int *new_sock;

    /* Create socket */
    sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
    if (sk < 0) {
        syslog(LOG_ERR, "Can't create socket: %s (%d)",
                            strerror(errno), errno);
        exit(1);
    }

    /* Bind to local address */
    memset(&addr, 0, sizeof(addr));
    addr.sco_family = AF_BLUETOOTH;
    bacpy(&addr.sco_bdaddr, &bdaddr);

    if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        syslog(LOG_ERR, "Can't bind socket: %s (%d)",
                            strerror(errno), errno);
        goto error;
    }

    /* Listen for connections */
    if (listen(sk, 10)) {
        syslog(LOG_ERR,"Can not listen on the socket: %s (%d)",
                            strerror(errno), errno);
        goto error;
    }

    syslog(LOG_INFO,"Waiting for connection ...");
    while (1) 
    {
        memset(&addr, 0, sizeof(addr));
        optlen = sizeof(addr);

        nsk = accept(sk, (struct sockaddr *) &addr, &optlen);
        if (nsk < 0) 
        {
            syslog(LOG_ERR,"Accept failed: %s (%d)",
                            strerror(errno), errno);
            goto error;
        }
        if( fcntl( nsk, F_SETFL, O_NONBLOCK ) < 0 )
        {
         printf(" failed to set non blocking ...\n");
         close( nsk );
         goto error;

        }

        /* Get connection information */
        memset(&conn, 0, sizeof(conn));
        optlen = sizeof(conn);

        if (getsockopt(nsk, SOL_SCO, SCO_CONNINFO, &conn, &optlen) < 0)
        {
            syslog(LOG_ERR, "Can't get SCO connection information: %s (%d)",
                            strerror(errno), errno);
            close(nsk);
            goto error;
        }

        ba2str(&addr.sco_bdaddr, ba);
        syslog(LOG_INFO, "Connect from %s [handle %d, class 0x%02x%02x%02x]",
            ba, conn.hci_handle,
            conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]);

        pthread_t sniffer_thread;
        new_sock = malloc(1);
        *new_sock = nsk;

        if( pthread_create( &sniffer_thread, NULL, connection_handler, (void*)new_sock )< 0 )
        {
          perror(" could not create thread");
          return 1;

        }

        // HERE CHECK IF SNIFFER_THREAD IS RUNNING OR NOT. 
//IF SINIFFER THREAD IS NOT RUNNING THEN CLOSE NSK?
// ANd that will terminate the server?
        puts (" handler assigned");

    }

    return 0 ;

error:
    close(sk);
    exit(1);
}

void *connection_handler( void *socket_desc)
{
  // get socket descriptor
 int sock = *(int*)socket_desc;

 int read_size;

 char*message, message_client[ 200 ];

  //receive messgae from client 
 while( read_size = recv( sock, message_client, 200, 0 ) > 0 )
 {
   printf(" very good\n"); 
 }
 if( read_size == 0 )
 {
  printf("clinet disconnected \n");
  fflush( stdout);
 }
 else if( read_size == -1 )
 {
  printf("received failed \n"); 
  perror( " recv fialed");
 }

 printf(" before memeory freee\n");
 free( socket_desc );

 return 0;

}
  • 0
    Я немного запутался. Если вы собираетесь создать поток для чтения, почему вы установили сокет как неблокирующий?
Теги:
pthreads

1 ответ

3
Лучший ответ

Поместите всю функциональность сервера в один поток, как цикл accept(), так и recv(). После этого accept() будет когда-либо вызываться один раз, поэтому он может возвращаться только один раз, поэтому только одно соединение будет принято. Когда клиент отключается, (то есть recv() возвращает 0), очистите, закрыв слуховой разъем и завершите поток. Если соединение закрывается (например, сбой питания у клиента), поток может зависеть вечно, застрял на recv(), но эй, кого это волнует? Вы можете использовать KEEPALIVE для окончательного закрытия сокетов и прекращения потока, но в этом нет никакой реальной необходимости - его код и стек в конечном итоге будут выгружены, а он потерян и потерян в пространстве (mehh..sob..).

Ох - и избавьтесь от NON_BLOCKING. Я не понимаю, почему вы его установили в первую очередь? Вы впитываете одно ядро для следующего-ничего, за исключением случая с половиной закрытия, и в этом случае вы впитываете одно ядро для абсолютно ничего.

  • 0
    Большое спасибо друг за помощь. С вопросом Keepalive, когда я пытаюсь добавить его в свой код, приложение падает. Я предполагаю, что у Bluetooth SCO Server такой опции нет. пример optval = 1; optlen = sizeof (optval); if (setsockopt (s, SOL_SCO, SO_KEEPALIVE, & optval, optlen) <0) {perror ("setsockopt ()"); близко (ы); Выход (EXIT_FAILURE); }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню