关于C#:从主线程关闭套接字

Close a socket from the main thread

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

这是我的对等代码:


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#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)。

要使其线程安全,可以使用添加互斥锁来声明对象

1
2
3
4
typedef struct {
    pthread_mutex_t mutex;
    int active;
} thread_state_t;

并添加一些类似这些的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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调用为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的另一种方法。但是,这不是最佳解决方案。