Implementing a sequential web proxy
先搞清listen socket 和 connected socket 的区别。
一个套接字对标记着一个客户端和服务器的链接。
客户端是发起连接请求的主动实体,而内核会认为socket函数创建的套接字是主动套接字,而服务器就是要调用listen函数告诉内核,该套接字是被服务器而不是客户端使用的,即listen函数将一个主动套接字转化为监听套接字。
服务器通过accept函数等待来自客户端的连接请求到达监听套接字,并返回一个已连接套接字,这个connfd可以被用来与客户端进行通讯。
实验过程如下:
some def
1 | /* You won't lose style points for including this long line in your code */ |
main 函数,参考课本的tiny服务器,注意的是这里pthread_create是传值而不是引用,是为了避免竞争。(传值是传一个独立的副本)
1 | int main(int argc,char **argv) |
多线程并发
1 | void *thread(void *vargp){ |
doit
函数逻辑:
1.得到解析后的请求行和请求头
2.然后去连接对应的服务器,发送请求
3.建立连接后,返回信息会在描述符中,也就是endServerFd
4.再把信息从endServerFd中读取出来,直接写进客户端对应的描述符fd就可以。
1 |
|
build HTTP that send to the end server
1 | void buildHTTPHeader(char *http_header,char *hostname,char *path,int port,rio_t *client_rio){ |
parseuri
1 |
|
connect end server
1 | inline int connectEndServer(char *hostname,int port){ |
cache
采用读者-写者模型,可以让多个线程同时来读。
没有实现LRU,只是简单地把1MiB内存分为十块,每次接受请求并解析之后,先去cache看看有没有对应的web object,如果有直接返回给客户端,没有再从服务端请求。
1 |
|
Test
use ./free-port.sh to get a free port, like 4501
open a terminal, nc -l 4501
- this is to start netcat as a server listening on port you get
open a terminal
1 | curl -v --proxy http://localhost:23885/ http://localhost:4501/ |
- open a terminal
./proxy 23885
netcat is listening on 4501,proxy is listening on 23885,here netcat serves as a server,print sth in the ‘nc -l’ window,then you can see the exact sth print on the ‘curl’ window