在多线程的网络服务器程序中, 对同一个客户端多线程同时发送数据是经常可能发生的事情, 也就是有可能会多
线程的对一个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;
}
反复执行程序会发现, 客户端收到的数据段,重复数据全部是连续的, 没有一次非连续数据出现, 这已经说明,操作系统在write/send的时候,会对socket的写缓冲区加锁。其实无论是linux还是windows,Socket都是线程安全的。
所以程序不用担心也不需要对套接字进行同步了。