HTTP超文本传输协议,它是应用层的协议,底层是基于TCP通信的,因此,实现web服务器的第一步至少要能实现两个主机不同进程之间的TCP通信,这部分可基于socket来实现。服务器端:创建sock->绑定(将sock文件描述符和ip地址端口号绑定在一起)-> 设置服务器为监听模式->accept->服务器创建线程去循环读写(创建一个新线程去单独处理一个客户端的请求)客户端·:创建sock->connect连接到服务器->循环读写。
HTTP协议的通信是一问一答形式,客户端通过浏览器发送一个URL请求,浏览器打包成HTTP报文格式,服务器进行响应,以报文格式响客户端请求的网页或者资源。
http协议的URL格式: http: //user:password@host[:port][abs_path]
报文格式定义参考:https://blog.csdn.net/wwxy1995/article/details/95517077?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
服务端代码框架实现如下:
int eolserver_init()
{
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
exit(1);
}
int opt = 1;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(IP_PORT_EOL);
int ret = bind(sock,(struct sockaddr *)&local,sizeof(local));
if( ret < 0 )
{
exit(2);
}
if( listen(sock,5) < 0 )
{
exit(3);
}
return sock;
}
int main(void)
{
int listen_sock = eolserver_init();
while(1)
{
struct sockaddr_in client;
socklen_t len = sizeof(client);
int sock = accept(listen_sock,(struct sockaddr*)&client,&len);
if(sock < 0)
{
continue;
}
char buf[4896] = {0};
ssize_t s = read(sock,buf,sizeof(buf)-1);
DLOGD("http recv : %s ",buf);
if( s > 0 )
{
char echo_str[2000] = {0};
httpserver_handler_recvdata(buf);
sleep(1);
httpserver_response_handler(echo_str);
//const char *echo_str = "HTTP/1.0 200 ok\n\n<html><h1>Welcome to my http server!</h1><html>\n";
write(sock,echo_str,strlen(echo_str));
}
close(sock);
}
return 0;
}
httpserver_handler_recvdata()用来解析收到的http包,httpserver_response_handler()填入应答的http报文。