http服务器
http协议的特点 http协议的格式 1)http协议中的方法 2)http协议中的状态码 3)http协议常见的Header
浏览器中的Cookie文件 实现简单的http服务器!!!
http协议的特点
无连接的:底层使用tcp传输控制协议,但是本身是无连接的; 无状态的:不会记录用户的任何信息; 简单、快速:connection表示其是连接类型,长链接----keep-alive,短连接----close。
http协议的格式
注:http协议按行传递请求和相应报头信息,以空格分割报头和有效载荷;
1)http协议中的方法
GET方法:直接获取资源,可通过url传参 ,数据不敏感; POST方法:将数据提交给服务器,通过正文传参 ,正文的大小可通过Content-Length获取,更私密;
2)http协议中的状态码
常见的状态码:200----OK ,302----redirect重定向 ,403----Forbidden,404----Not Found,504----Bad Gateway
3)http协议常见的Header
Content-Type 数据类型(text/html等) Content-Length Body的长度 Host 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上; User-Agent 声明用户的操作系统和浏览器版本信息 referer 当前页面是从哪个页面跳转过来的 location 搭配3xx状态码 使用, 告诉客户端接下来要去哪里访问 Cookie 用于在客户端存储少量信息. 通常用于实现会话(session)的功能
浏览器中的Cookie文件
当客户端向服务器端发送请求时,服务器会发送响应,并把name、password通过set-cookie保存到浏览器,下次浏览器发送请求时会自动带上cookie文件,然后服务器开始自动认证;服务器认证通过后,形成sid,并把sid和相关信息写入到session文件中,从此以后返回到客户端的信息就是set-cookie:sid=xxx,客户端再把sid保存到cookie文件中;以后客户端使用cookie里面的sid,然后服务器去寻找自己所拥有的session文件中的sid。
实现简单的http服务器!!!
在httpServer.hpp文件中,实现http服务器的主逻辑:接受客户端发送的请求,按http响应格式发送响应给客户端
# define BACKLOG 5
# define PAGE "index.html"
struct server {
private :
int port;
int lsock;
public :
server ( int _port) : port ( _port) , lsock ( - 1 ) {
}
void initServer ( ) {
lsock = socket ( AF_INET, SOCK_STREAM, 0 ) ;
if ( lsock < 0 ) {
std:: cout << "socket error!" << std:: endl;
exit ( 2 ) ;
}
std:: cout << "lsock:" << lsock << std:: endl;
struct sockaddr_in local;
local. sin_family = AF_INET;
local. sin_port = htons ( port) ;
local. sin_addr. s_addr = INADDR_ANY;
if ( bind ( lsock, ( struct sockaddr * ) & local, sizeof ( local) ) < 0 ) {
std:: cout << "bind error!" << std:: endl;
exit ( 3 ) ;
}
if ( listen ( lsock, BACKLOG) < 0 ) {
std:: cout << "listen error!" << std:: endl;
exit ( 4 ) ;
}
}
void start ( ) {
struct sockaddr_in peer;
socklen_t len = sizeof ( peer) ;
while ( true ) {
int sock = accept ( lsock, ( struct sockaddr * ) & peer, & len) ;
if ( sock < 0 ) {
std:: cout << "accept error!" << std:: endl;
continue ;
}
char buf[ 16 ] ;
sprintf ( buf, "%d" , ntohs ( peer. sin_port) ) ;
std:: string cli = inet_ntoa ( peer. sin_addr) ;
cli += ":" ;
cli += buf;
std:: cout << "client info: " << cli << " sock:" << sock << std:: endl;
if ( fork ( ) == 0 ) {
if ( fork ( ) > 0 ) {
exit ( 0 ) ;
}
close ( lsock) ;
EchoHttp ( sock) ;
exit ( 0 ) ;
}
close ( sock) ;
}
}
void EchoHttp ( int sock) {
std:: cout << "############ http request begin ##############" << std:: endl;
std:: ifstream in ( PAGE) ;
if ( in. is_open ( ) ) {
in. seekg ( 0 , std:: ios:: end) ;
size_t len = in. tellg ( ) ;
in. seekg ( 0 , std:: ios:: beg) ;
char * file = new char [ len] ;
in. read ( file, len) ;
in. close ( ) ;
std:: string status_line = "http/1.0 307 Temporary Redirect\n" ;
std:: string response_header = "Content_Length: " + std:: to_string ( len) ;
response_header += "\n" ;
response_header += "location: http://www.qq.com/" ;
response_header += "\n" ;
std:: string blank = "\n" ;
send ( sock, status_line. c_str ( ) , status_line. size ( ) , 0 ) ;
send ( sock, response_header. c_str ( ) , response_header. size ( ) , 0 ) ;
send ( sock, blank. c_str ( ) , blank. size ( ) , 0 ) ;
send ( sock, file, len, 0 ) ;
delete [ ] file;
}
std:: cout << "############ http request end ###############" << std:: endl;
close ( sock) ;
exit ( 0 ) ;
}
~ server ( ) {
close ( lsock) ;
}
} ;
在httpServer.cc文件中,启动http服务器,等待客户端连接、发送请求
void Usage ( std:: string proc) {
std:: cout << proc << "server_port" << std:: endl;
}
int main ( int argc, char * argv[ ] ) {
if ( argc != 2 ) {
Usage ( argv[ 0 ] ) ;
exit ( 1 ) ;
}
server * sp = new server ( atoi ( argv[ 1 ] ) ) ;
sp-> initServer ( ) ;
sp-> start ( ) ;
delete sp;
return 0 ;
}