socket的write/send还是是否是线程安全?

    在多线程的网络服务器程序中, 对同一个客户端多线程同时发送数据是经常可能发生的事情, 也就是有可能会多

线程的对一个fd调用send/write, 那么这种操作是否需要加锁?并发写套接字是否导致系统缓冲区数据混乱呢? 网上搜

了下,有人说可以写,有人说不能,linux man page也没有说明。 看来需要写程序测试。 写了个server的代码进行

测试。


10个线程同时对一个fd进行write, 看看客户端会收到什么数据。


服务端代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

int sockfd;

inline void mysend(const char *s) {
    const char *s = (const char*)p;
    printf("written %d\n", write(sockfd, s, strlen(s)));
}

void *func1(void *p) {
    mysend(p);
    return 0;
}

void *func2(void *p) {
    mysend(p);
    return 0;
}

void *func3(void *p) {
    mysend(p);
    return 0;
}
void *func4(void *p) {
    mysend(p);
    return 0;
}

void *func5(void *p) {
    mysend(p);
    return 0;
}

void *func6(void *p) {
    mysend(p);
    return 0;
}

void *func7(void *p) {
    mysend(p);
    return 0;
}

void *func8(void *p) {
    mysend(p);
    return 0;
}

void *func9(void *p) {
    mysend(p);
    return 0;
}

void *func10(void *p) {
    mysend(p);
    return 0;
}
void *(*funcArray[])(void*) = { func1, func2, func3,func4,func5,func6,func7,func8,func9,func10 };

const char *paramArray[] = {"11111111111111111111111111111111", "22222222222222222222222222222222222222222222222222",
                            "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
                            "Cccccccccccccccccccccccc", "Ddddddddddddddddddddd", "Eeeeeeeeeeeeeeeeeee", "Fffffffffffffffffffffff",
                            "Ggggggggggggggggggggggggg", "Oooooooooooooooooooooooooooooooooooooooooooooooooooo" };

int main() {
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sigaction( SIGPIPE, &sa, 0 );
    char recvbuf[RECV_BUF_LEN];
    struct sockaddr_in addr;

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("error.");
        return 0;
    }
    int val = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(6666);
    bind(fd, (struct sockaddr*)&addr, sizeof(addr));

    listen(fd, 100);

  while (true) {
        struct sockaddr_in cli_addr;
        socklen_t socklen = sizeof(cli_addr);
        sockfd = accept(fd, (struct sockaddr*)&cli_addr, &socklen);

        if (fd == -1) {
            perror("accept");
            exit(0);
        }
        printf("accept new connection : %d\n", fd);

        pthread_t tt[10];

        for (int i = 0; i < 10; ++i) {
            pthread_create(&tt[i],NULL, funcArray[0], (void*)paramArray[i]);
        }
        for (int i = 0; i < 10; ++i) {
            pthread_join(tt[i], NULL);
        }

        printf("done\n");
    }
    return 0;
}



客户端用python简单写个测试程序

from socket import *
import time

sock = socket(AF_INET, SOCK_STREAM, 0)
sock.connect(('192.168.42.128', 3333))


while True:
    recvbuf = sock.recv(1024)
    print recvbuf
    time.sleep(1)

     反复执行程序会发现, 客户端收到的数据段,重复数据全部是连续的, 没有一次非连续数据出现, 这已经说明,操作系统在write/send的时候,会对socket的写缓冲区加锁。其实无论是linux还是windows,Socket都是线程安全的。


    所以程序不用担心也不需要对套接字进行同步了。

你可能感兴趣的:(TCP/IP网络编程,Linux系统编程)