【问题标题】:Threading to connect to different servers has unpredicatble outcome连接到不同服务器的线程具有不可预测的结果
【发布时间】:2020-04-21 08:00:05
【问题描述】:

我有两台服务器在指定的端口上运行。

我正在尝试使用线程并行连接它们。

当我不进行线程处理时,代码可以按需要运行。

int main(){
    // Server 1
    char* ip1[]={"127.0.0.1","42069"};
    // Server 2
    char* ip2[]={"127.0.0.1","42070"};

    file_l *file = create_file_l("file.txt",ROOT);
    if(file->size != 0)
        return -1;
    // Common Data Structure that is sent to both threads to prevent overwriting
    file_n *filen = create_file_n(file);
    filen->part_size = 1024*1024*16;

    add_seed(ip1, filen);
    add_seed(ip2, filen);
    return 1;
}

add_seed 函数连接到给定的服务器并创建一个新线程来处理来自该服务器的数据。

int add_seed(char* ip[], file_n* n){
    // Connects to given address and goes file descriptor
    int cfd = connectTo(ip);
    if(cfd==-1)return -1;

    // Data Structure Used to pass parameters to both threads
    conn_det *cd  = malloc(sizeof *cd);
    cd->socket = cfd;cd->file = n;
    // Thread Creation
    pthread_t temp;
    pthread_create(&temp,NULL,initiate_data_transfer,cd);
    pthread_detach(temp);
    return 1;
}

initiate_data_transfer 函数发送数据请求并处理来自服务器的传入响应。

void* initiate_data_transfer(void *ptr){
    printf("Thread ID : %ld\n",syscall(SYS_gettid));
    conn_det *cd = ptr;
    file_n *n = cd->file;
    int socket = cd->socket;int rv=-1;
    long size = check_if_available(socket, n->local->name);
    printf("Recv Size : %ld Thread ID : %ld\n",size,syscall(SYS_gettid));

    // Checks if file size has been set by some other thread
    pthread_mutex_lock(&(n->mutex));
        if(n->local->size == 0){           // If not , assign file_size
            n->local->size = size;
            initialize_file_n(n);
        }else{
            if(n->local->size != size){    // If yes and size from this server does not match, then exit.
                pthread_mutex_unlock(&(n->mutex));
                return NULL;
            }
        }
    pthread_mutex_unlock(&(n->mutex));
    // Data Transfer Part.
    printf("Size : %ld Thread ID : %ld\n",n->local->size,syscall(SYS_gettid));
    while((rv=get_part(n)) != -1){
        printf("Handling Part : %d Thread ID : %ld\n",rv,syscall(SYS_gettid));
        send_fetch_request(socket,n,rv);
        recv_fetch_response(socket,n,rv);
    }

    close(socket);
}

用于将信息传递给线程的数据结构。

typedef struct File_information_Network{
    long part_size;
    long total_parts;
    int* parts_recieved;
    file_l *local;
    pthread_mutex_t mutex;
}file_n;

typedef struct Connection_Details
{
    int socket;
    file_n *file;
}conn_det;

问题是大部分时间只有一个线程到达initiate_data_transfer函数。

这可以从printf("Thread ID : %ld\n", syscall(SYS_gettid));initiate_data_transfer 的第一行)在大多数情况下运行一次这一事实中看出,而我创建了两个线程。

考虑以下日志:

客户终端:

user@machine:~/Desktop/cn/FileShare/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3164
Connected to: 127.0.0.1
user@machine:~/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3169
Connected to: 127.0.0.1
user@machine:~/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3174
Connected to: 127.0.0.1
user@machine:~/path$ ./a.out 
Connected to: 127.0.0.1
Thread ID : 3179
Connected to: 127.0.0.1
Thread ID : 3180

我不知道出了什么问题,使用printf 进行调试根本无法帮助我解决这个问题。任何帮助表示赞赏。

【问题讨论】:

    标签: c multithreading networking pthreads


    【解决方案1】:

    我怀疑主线程只是在两个线程到达initiate_data_transfer 并开始工作之前就退出了。

    虽然你已经分离了新创建的线程,但是main线程的返回仍然会退出进程。

    所以而不是:

    return 1;
    

    来自main,做:

    pthread_exit(0);
    

    这会让线程继续进行。当最后一个线程退出时,进程会自动退出。

    【讨论】:

    • 这就是问题所在。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2013-01-06
    • 1970-01-01
    • 2013-01-04
    • 2012-12-24
    • 2011-04-15
    • 1970-01-01
    相关资源
    最近更新 更多