简体   繁体   中英

Close a socket from the main thread

I'm implementing a P2P file transfer with a peer and a tracker. The tracker keeps track of all the peers and their files, and the peer connects to another peer when wanting to download a file and also accepts requests from other peers to download one of its files. For this, my peer is acting as both a client and a server to other peers, and a client to the tracker. To do so, I am using threads and have the server process in one thread, the client process in another, and the one connecting to the tracker in the main thread. When the peer chooses to exit, I want to close its server process as well ie: the process in the separate server thread. I tried making a global variable containing the file descriptor so then I can close it when the client exits, but this is giving me an error after I exit.

Here is my peer code:

If you want to know how to stop other threads from main thread here is one method. I would create a struct let's call it thread_state_t which has a flag that tells your threads to stop, call it active for example. In thread you check in the loop its value and do whatever you need based on state.

In simple case it will look like this

#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;
}

However this example is just to show you the main idea. In real implementation you need to make active variable or whole thread_state_t object thread safe (use mutex for example).

To make it thread safe you can use add mutex to state object

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

and add some functions like these

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);
}

Then change loop condition from state->active > 0 to get_active(state) > 0 and your code in main thread will look like this ( sleep call here is for example only)

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;
}

Also another way to use pthread_cancel . However this is not the best solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM