从主线程关闭套接字

时间:2015-10-15 04:24:00

标签: c multithreading sockets network-programming pthreads

我正在与对等方和跟踪器一起实现P2P文件传输。跟踪器跟踪所有对等体及其文件,并且对等体在想要下载文件时连接到另一个对等体,并且还接受来自其他对等体的请求以下载其中一个文件。为此,我的对等体既充当客户端又充当其他对等体的服务器,以及充当跟踪器的客户端。为此,我使用线程并在一个线程中使用服务器进程,在另一个线程中使用客户端进程,并在主线程中连接到跟踪器。当对等体选择退出时,我想关闭其服务器进程,即:单独服务器线程中的进程。我尝试创建一个包含文件描述符的全局变量,然后我可以在客户端退出时将其关闭,但是在退出后这会给我一个错误。

这是我的同行代码:

1 个答案:

答案 0 :(得分:0)

如果你想知道如何从主线程中停止其他线程,这是一种方法。我会创建一个结构让我们称之为thread_state_t,它有一个告诉你的线程停止的标志,例如调用它active。在线程中,您可以在循环中检查其值,并根据状态执行您需要的任何操作。

在简单的情况下,它看起来像这样

#include <stdio.h>
#include <pthread.h>

typedef struct {
    int active;
} thread_state_t;

void* t1(void* arg) {
    thread_state_t* state = (thread_state_t*) arg;
    while(state->active > 0) {
        // do work
    }
    return NULL;
}

int main() {
    pthread_t tid;
    thread_state_t state1;
    state1.active = 1;

    pthread_create(&tid, NULL, t1, (void*)&state1);

    // ...
    state1.active = 0;
    // ...

    pthread_join(tid, NULL);

    return 0;
}

然而,这个例子只是为了向您展示主要想法。在实际实现中,您需要使active变量或整个thread_state_t对象线程安全(例如,使用mutex)。

为了使其线程安全,您可以使用add mutex添加到状态对象

typedef struct {
    pthread_mutex_t mutex;
    int active;
} thread_state_t;

并添加一些这样的功能

void init_state(thread_state_t* state) {
    state->active = 1;
    pthread_mutex_init(&state->mutex, NULL);
}

void remove_state(thread_state_t* state) {
   state->active = 0;
   pthread_mutex_destroy(&state->mutex);
}

int get_active(thread_state_t* state) {
    int active = 0;
    pthread_mutex_lock(&state->mutex);
    active = state->active;
    pthread_mutex_unlock(&state->mutex);
    return active;
}

void set_active(thread_state_t* state, int active) {
    pthread_mutex_lock(&state->mutex);
    state->active = active;
    pthread_mutex_unlock(&state->mutex);
}

然后将循环条件从state->active > 0更改为get_active(state) > 0,并且主线程中的代码将如下所示(此处sleep调用仅作为示例)

int main() {
    pthread_t tid;
    thread_state_t state;
    init_state(&state);

    pthread_create(&tid, NULL, t1, (void*)&state);

    sleep(1);
    set_active(&state, 0);

    pthread_join(tid, NULL);
    remove_state(&state);

    return 0;
}

使用pthread_cancel的另一种方法。然而,这不是最佳解决方案。