Unix Network Programming - 4. 多线程I/O

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "Common.h"

void str_echo(int sockfd) {
char buffer[MAXLINE];

while (1) {
int n = read(sockfd, buffer, MAXLINE);
if (n <= 0 && errno == EINTR) {
std::cout << "read errno -> EINTR" << std::endl;
}
else if (n <= 0)
{
std::cout << "read return <= 0" << std::endl;
break;
}
if(n > 0) write(sockfd, buffer, n);
}
}

void* doit(void* args){
pthread_detach(pthread_self());
str_echo(*(int*)args);
close(*(int*)args);
return nullptr;
}

int main() {
int listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sockfd < 0) {
std::cout << "create blank socket failure." << std::endl;
}

sockaddr_in socket_addr;
bzero(&socket_addr, sizeof(socket_addr));
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 等到TCP连接成功后选择IP地址
socket_addr.sin_port = htons(SERVER_PORT);

if (bind(listen_sockfd, (sockaddr*)& socket_addr, sizeof(socket_addr)) < 0) {
std::cout << "bind socket address failure." << std::endl;
}

if (listen(listen_sockfd, LISTENQ) < 0) {
std::cout << "listening socket create failure." << std::endl;
}

sockaddr_in client_addr;
socklen_t clilen = sizeof(client_addr);
while (1) {
int connect_sockfd = accept(listen_sockfd, (sockaddr*)&client_addr,&clilen);

pthread_t tid;
pthread_create(&tid, 0, doit, (void*)connect_sockfd);
}
}

多个线程同时访问同一个connect_sockfd

线程传递参数的问题,

线程特定数据 pthread_key_create

互斥锁:

互斥锁变量是静态分配的, 那么需要使用PTHREAD_MUTEX_INITIALIZER初始化
如果在共享内存区分配一个互斥锁, 需要调用pthread_mutex_init函数在运行时初始化
pthread_mutex_t = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_lock(pthread_mutex_t *pmutex);

pthread_mutex_unlock(pthread_mutex_t *pmutex);

互斥锁的开销: 做实验比较, 开销并不大

条件变量

互斥锁用于防止同时访问某个共享变量
需要某种待等待某个条件发生期间能够让之进入睡眠的东西, 避免轮询

互斥锁提供互斥机制, 条件变量提供信号机制

pthread_cond_t = PTHREAD_COND_INITIALIZER;

int pthread_cond_wait(pthread_cond_t pcond, pthread_mutex_t *pmutex);
int pthread_cond_signal(pthread_cond_t *pcond);
int pthread_cond_boardcast(pthread_cond_t *cptr);
int pthread_cond_timedwait(pthread_cond_t
cptr, pthread_mutex_t* mptr, const struct timespec* abstime);