5

我想知道如果两个线程同时调用同一个函数并且该函数是一个通过套接字发送文本的 UDP 客户端会发生什么。

考虑到下面的代码,我一直在运行它,但还没有出现任何错误。我想知道它是否应该因为线程同时使用相同的源(函数、变量、IP、端口)而崩溃,它们如何共享源?我可以想象下面的代码是多线程的错误用法,你能解释一下应该如何使用线程,以便一个线程只使用没有其他线程使用的函数吗?换句话说,它怎么可能是线程安全的?

作为 Linux 上的示例 C 代码:

void *thread1_fcn();
void *thread2_fcn();
void msg_send(char *message);

int main(void){
    pthread_t thread1, thread2;
    pthread_create( &thread1, NULL, thread1_fcn,  NULL);
    pthread_create( &thread2, NULL, thread2_fcn,  NULL);
    while(1){}
    return 0;
}

void *thread1_fcn(){
    while(1){
        msg_send("hello");
        usleep(500);
    }
    pthread_exit(NULL);
}

void *thread2_fcn(){
    while(1){
        msg_send("world");
        usleep(500);
    }
    pthread_exit(NULL);
}

void msg_send(char message[]){
       struct sockaddr_in si_other;
       int s=0;
       char SRV_IP[16] = "192.168.000.002";

        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        memset((char *) &si_other, 0, sizeof(si_other));
        si_other.sin_family = AF_INET;
        si_other.sin_port = htons(12346);
        si_other.sin_addr.s_addr = htonl(INADDR_ANY);
        inet_aton(SRV_IP, &si_other.sin_addr);
        sendto(s, message, 1000, 0, &si_other, sizeof(si_other));
        close(s);
}
4

3 回答 3

4

您的代码没有任何问题。每个线程,即使它运行相同的代码,也有一个单独的堆栈,因此它可以处理一组单独的变量。没有变量是共享的。

于 2013-06-26T21:08:47.443 回答
3

由于您在内部创建并关闭了套接字msg_send,因此不会发生什么特别的事情。一切都会好起来的。

于 2013-06-26T21:08:28.390 回答
1

您的代码调用未定义的行为,因为线程将小字符串文字作为message参数传递,但该函数尝试从message基地址开始发送 1000 个字节。

由于sendto通常是对操作系统的直接调用,要么您将通过 UDP 发送大量垃圾(或更糟糕的是:安全敏感信息!),要么系统调用将检测到越界内存访问并返回 -1 并设置 errno类似于EFAULT(可能没有发送任何数据)。

因为message是一个字符串,你应该计算它的长度,然后只发送那个数量(有或没有空终止符;这取决于你。接收者可以从数据报的长度重建一个空终止的字符串。)

不过,该函数不会引发并发问题。

sendto即使多个线程在同一个套接字上调用它,该函数也是安全的。但是,如果您在流套接字上执行此操作,您可能会遇到数据以不可预知的方式交错到字节流中的问题。

于 2013-06-27T06:39:00.317 回答