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
56
57
58
|
#include <stdio.h>
#include "csapp.h"
/* Recommended max cache and object sizes */
#define MAX_CACHE_SIZE 1049000
#define MAX_OBJECT_SIZE 102400
void doit(int fd);
int parse_uri(char *uri, char *hostname, char *path, int *port);
void makeHTTPheader(char *http_header, char *hostname, char *path, int port, rio_t *client_rio);
void *thread_routine(void *connfdp);
int main(int argc, char **argv)
{
int listenfd;
char hostname[MAXLINE], port[MAXLINE];
socklen_t clientlen;
struct sockaddr_storage clientaddr;
pthread_t tid;
if (argc != 2)
{
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(1);
}
listenfd = Open_listenfd(argv[1]);
while (1)
{
// sever main에서 일련의 처리를 하는 대신 스레드를 분기
// 각 연결에 대해 이후의 과정은 스레드 내에서 병렬적으로 처리되며
// main은 다시 while문의 처음으로 돌아가 새로운 연결을 기다린다
clientlen = sizeof(clientaddr);
// 이때 각 스레드는 모두 각각의 connfd를 가져야 하기 때문에, 연결마다 메모리를 할당하여 포인팅한다
int *connfdp = Malloc(sizeof(int));
*connfdp = Accept(listenfd, (SA *)&clientaddr, &clientlen);
Getnameinfo((SA *)&clientaddr, clientlen, hostname, MAXLINE, port, MAXLINE, 0);
printf("Accepted connection from (%s, %s)\n", hostname, port);
// thread_routine를 실행하는 thread 생성
// 연결마다 고유한 connfdp를 thread_routine의 입력으로 가져간다
Pthread_create(&tid, NULL, thread_routine, connfdp);
}
return 0;
}
void *thread_routine(void *connfdp)
{
// 각 스레드별 connfd는 입력으로 가져온 connfdp가 가리키던 할당된 위치의 fd값
int connfd = *((int *)connfdp);
// 스레드 종료시 자원을 반납하고
Pthread_detach(pthread_self());
// connfdp도 이미 connfd를 얻어 역할을 다했으니 반납한다
Free(connfdp);
doit(connfd);
Close(connfd);
return NULL;
}
// 이후 각 스레드의 수행은 seqential과 같으니 생략
|
cs |
터미널을 하나 더 켜듯이 스레드를 하나 더 만드는 것으로 병렬 처리가 가능하다.
주의해야할 점이 둘 있다면
1. 각 스레드마다 각각의 fd를 가져야한다. 스레드의 상한이 유한하게 예측이 된다면 미리 그만큼의 배열을 할당하면 될 것이고, 지금처럼 상한이 예측이 안된다면 malloc으로 동적 할당하여(각 스레드에 진입하면 free해야 함) 고유성을 확보해야 할 것이다.
2. malloc을 다 쓰면 free로 반납하듯이 각 스레드도 detach로 자원을 반납해야 한다. 스레드를 쓰는 용도에 따라 자원을 남겨야 할 경우도 있겠지만, proxy server에서는 이미 역할을 끝낸 연결의 잔해를 굳이 남겨 자원을 차지할 필요는 없을 것이다.
벌써 12시인데 part 3 캐시를 끝낼 수 있을까...
'Week 05 ~ 07 : 전산학 프로젝트 > SW정글 Week 07 : Web Server' 카테고리의 다른 글
[Web Server] 5. web proxy 구현 part III (w/ cache) (0) | 2021.12.23 |
---|---|
[Web Server] 3. web proxy 구현 part I (sequential) (0) | 2021.12.22 |
[Web Server] 2. tiny 웹서버 구현 (dynamic - html) (0) | 2021.12.22 |
[Web Server] 1. tiny 웹서버 구현 (static) (0) | 2021.12.21 |