首页 >> 大全

HTTP协议

2023-12-11 大全 29 作者:考证青年

分为请求报文和响应报文,ASCII编码的字段组成

HTTP/1.1 301 Moved {永久转移}

: :port//.html {新的URL}

与间传递的状态信息

HTML

超文本标记语言

<html><head><title>好诗title>head><body> <H1>一级标题H1><H2>春江花月夜H2><p>春江潮水连海平,海上明月共潮生。<br>滟滟随波千万里,何处春江无月明! <br>江流宛转绕芳甸,月照花林皆似霰; <br>空里流霜不觉飞,汀上白沙看不见。 <br>江天一色无纤尘,皎皎空中孤月轮。 <br>江畔何人初见月?江月何年初照人? <br>人生代代无穷已,江月年年望相似。P><p>My UNIX do not have Chiness charactor setP>body>
html>

使用ASCII编码,浏览器直接打开查看效果

HTML允许在网页中插入图像(内含图像 image),其中gif格式压缩后体积最小

远程连接:终点在其他网站

本地连接:终点在本计算机

静态文档( )

工人写完后不再改变,简单但不灵活

动态文档( )

浏览器访问时程序动态创建

通用网关接口(CGI,

是一种定义动态文档的创建,数据输入(给应用程序) 和 输出的标准

CGI程序 是 脚本程序( )

活动文档( )

TCP/IP

了解套接字编程,主要

变量有:

(_fd)

函数有:

端的()、send()、recv()

端()、()

#include 
#include 
#include 
#include 
#include 
#include 
#include 
//-------------------
//V1.0 接收请求,显示报文
//-------------------
using namespace std;
int main(void)
{int listener=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(listener==(int)(~0)){	cout<<"Listenner Initiate Failure!"<<endl;return 0;}struct sockaddr_in ServerAddr;ServerAddr.sin_family=AF_INET;ServerAddr.sin_port=htons(8080); //http服务端口ServerAddr.sin_addr.s_addr=INADDR_ANY;if(bind(listener,(struct sockaddr*)&ServerAddr,sizeof(ServerAddr))== -1){cout<<"Binding Failure!"<<endl;return 0;}if(listen(listener,5)==-1){cout<<"Listening Start Failure!"<<endl;return 0;}int Client_id;struct sockaddr_in ClientAddr;socklen_t ClientAddrLen = sizeof(ClientAddr);while(1){cout<<"Listening..."<<endl;Client_id=accept(listener,(struct sockaddr*)&ClientAddr,&ClientAddrLen);if(Client_id==(int)(~0)){cout<<"Accept Error!"<<endl;continue;}cout<<"Accept message from Client :"<<endl;char recvData[512]={};recv(Client_id,recvData,512,0);cout<<recvData<<endl;const char* cmd=recvData;close(Client_id);if(!strcmp(cmd,"CloseServer"))break;}close(listener);return 0;
}

在Unix系统下运行以上源文件编写的,再使用其他主机上的浏览器通过URL访问任意上的资源,都会打印HTTP请求的内容

可以手写响应报文:

char sendData[512]={0};
strcpy(sendData,"HTTP/1.1 202 OK!\r\ncontent-type: text/html; charset=UTF-8\r\n\r\nTry

Title-C1

"
); send(Client_id,&sendData,512,0);

再使用其他主机上的浏览器通过URL访问任意上的资源,将返回响应报文

在浏览器中可以看到响应报文实体(html文档)在浏览器中显示的效果

按下F12使用控制台,刷新后重新访问URL,可查看响应报文的标头

文件存取

首先提取请求中的文件名,然后使用中的类open(请求的file),open()函数搜索可执行文件所在的目录下是否存在目标文件,成功打开后读取内容,并与HTTP的开始行、首部行,一并返回

//-----------------------------------
//V2.0 接受请求,分析URL,响应传输html文档
//-----------------------------------
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include using namespace std;
int main(void)
{int listener=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(listener==(int)(~0)){	cout<<"Listenner Initiate Failure!"<<endl;return 0;}struct sockaddr_in ServerAddr;ServerAddr.sin_family=AF_INET;ServerAddr.sin_port=htons(8080);ServerAddr.sin_addr.s_addr=INADDR_ANY;setsockopt(listener, SOL_SOCKET, SO_REUSEPORT, (char*)&ServerAddr, sizeof(ServerAddr));if(bind(listener,(struct sockaddr*)&ServerAddr,sizeof(ServerAddr))== -1){cout<<"Binding Failure!"<<endl;return 0;}if(listen(listener,5)==-1){cout<<"Listening Start!"<<endl;return 0;}int Client_id;struct sockaddr_in ClientAddr;socklen_t ClientAddrLen = sizeof(ClientAddr);while(1){cout<<"Listening..."<<endl;//--接收请求--Client_id=accept(listener,(struct sockaddr*)&ClientAddr,&ClientAddrLen);if(Client_id==(int)(~0)){cout<<"Accept Error!"<<endl;continue;}cout<<"Accept message from Client :"<<endl;char recvData[512]={0};recv(Client_id,recvData,512,0);recvData[511]='\0';cout<<recvData<<endl;//--处理请求--string fpath(recvData);string::size_type start=fpath.find('/');string::size_type end=fpath.find(' ',start);string fname = fpath.substr(start+1,end-start-1); //文件名提却ifstream inFile;string content;inFile.open(fname.c_str(), ios::in);if (inFile)  //条件成立,则说明文件打开成功{cout << "File Open Succuss!" << endl;string tmp;while(inFile>>tmp)content=content+tmp;cout<<content<<endl;inFile.close();}elsecout << "File doesn't exist" << endl;//--发送响应--char sendData[1024]={0};char httpHeader[255]={0};if(content.empty()) //404 not found httpheaderstrcpy(httpHeader,"HTTP/1.1 404 file not found!\r\n\r\n\0");else				//202 OK httpheaderstrcpy(httpHeader,"HTTP/1.1 202 OK!\r\ncontent-type: text/html; charset=UTF-8\r\n\r\n\0");cout<<httpHeader<<endl;strcpy(sendData,httpHeader);strcat(sendData,content.c_str());send(Client_id,&sendData,1024,0);//--关闭check--const char* cmd=recvData;close(Client_id);if(!strcmp(cmd,"CloseServer"))break;}close(listener);return 0;
}

进程与线程 线程间通信

(),recv()会阻塞,需要特别小心

如多线程项目中,收到退出信号后,阻塞态的主线程在收到(不可能到来的)下一个信号前,无法响应退出命令

可以将他们设置为非阻塞

并发回显测试

/* -----------------------------------------------------------------
Server.V3.0.CentOS 多线程接受,回显,主线程main中accept()会阻塞,CloseServer需发送两次以上
-------------------------------------------------------------------*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;#define ERROR ((int)(~0))
#define MAX_THREAD_NUM 4
#define MAX_REQ_NUM 512     bool exit_flag=false;
int thread_no[MAX_THREAD_NUM];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
vector<deque<int> > Client_id(MAX_THREAD_NUM);  //线程请求队列void *pthread_start_fcn(void *);                //线程启动函数
int find_shortest_deque(vector<deque<int> >&); //最短队列查找
bool empty_check(vector<deque<int> >&);        //空队列检测
bool full_check(vector<deque<int> >&);         //满队列检测int main(void)
{//监听套接字int listener=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(listener==ERROR){	cout<<"Listenner Initiate Failure!"<<endl;return 0;}struct sockaddr_in ServerAddr;ServerAddr.sin_family=AF_INET;ServerAddr.sin_port=htons(8080);ServerAddr.sin_addr.s_addr=INADDR_ANY;setsockopt(listener, SOL_SOCKET, SO_REUSEPORT, (char*)&ServerAddr, sizeof(ServerAddr));if(bind(listener,(struct sockaddr*)&ServerAddr,sizeof(ServerAddr))== -1){cout<<"Binding Failure!"<<endl;return 0;}if(listen(listener,5)==-1){cout<<"Listening Initiation Failure!"<<endl;return 0;}cout<<"Listening..."<<endl;//初始化处理线程pthread_mutex_lock(&lock);for (int i=0;i<MAX_THREAD_NUM;i++){thread_no[i]=i;pthread_t tmp;pthread_create(&tmp,NULL,pthread_start_fcn,&thread_no[i]);pthread_detach(tmp);}pthread_mutex_unlock(&lock);//开始接收套接字struct sockaddr_in ClientAddr;socklen_t ClientAddrLen = sizeof(ClientAddr);while(true){if(exit_flag==false){//--接收请求--//cout<<"Before Accept!"<int id = accept(listener,(struct sockaddr*)&ClientAddr,&ClientAddrLen);//cout<<"After Accept!"<if( id == ERROR ) {cout<<"Accept Error!"<<endl;continue;}else if (!full_check(Client_id)) //压入 请求队列最短的线程 处理{pthread_mutex_lock(&lock);Client_id[find_shortest_deque(Client_id)].push_back(id);pthread_mutex_unlock(&lock);}else  //队列满,放弃处理 关闭套接字close(id);}if(exit_flag==true)  //队列不空不能关闭break; //关闭服务器}close(listener);return 0;
}void *pthread_start_fcn(void *arg)
{int thread_no=*(int*)arg;while(1){if(!Client_id[thread_no].empty()) //队列非空{//上锁pthread_mutex_lock(&lock);int id = Client_id[thread_no][0];Client_id[thread_no].pop_front();pthread_mutex_unlock(&lock);//解锁--处理请求--char recv_data[512]={0};recv(id,recv_data,512,0);recv_data[511]='\0';cout<<recv_data<<endl;if(!strcmp(recv_data,"CloseServer")){exit_flag=true;cout<<"Kill:"<<endl;}elsesend(id,&recv_data,512,0);close(id);}else if(exit_flag == true){cout<<"T"<<thread_no<<endl;break;}}return NULL;
}int find_shortest_deque(vector<deque<int> > &Client_id)
{int shortest = 0;int min_req = MAX_REQ_NUM;for(int i=0;i<MAX_THREAD_NUM;i++){if(Client_id[i].size()<min_req){min_req = Client_id[i].size();shortest = i;}}return shortest;
}bool empty_check(vector<deque<int> > &Client_id)
{bool empty = true;for(int i=0;i<MAX_THREAD_NUM;i++)if(Client_id[i].size()>0){empty = false;break;}return empty;
}bool full_check(vector<deque<int> > &Client_id)
{bool full = true;for(int i=0;i<MAX_THREAD_NUM;i++)if(Client_id[i].size()<MAX_REQ_NUM){full = false;break;}return full;
}

/*
Client.3.0.windows. 并发回显测试Client端
须在Visual Studio的项目属性-->链接器-->命令行中输入"ws2_32.lib" 
*/
#include
#include
#include#pragma warning(disable : 4996)
#define REQ_NUM 50    //并发请求数量
char ip_addr[] = { "192.168.31.246" };
using namespace std;
int main(void)
{WORD socket_ver = MAKEWORD(2, 2);WSADATA data;if (WSAStartup(socket_ver, &data) != 0){cout << "WSAStartup failed!" << endl;return 0;}while (true){string input;cin >> input;if (!strcmp(input.c_str(), "CloseClient"))break;for (int i = 0; i < REQ_NUM; i++){SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (client == INVALID_SOCKET){cout << "Socket Init Failure!" << endl;continue;}sockaddr_in server;server.sin_family = AF_INET;server.sin_port = htons(8080);server.sin_addr.S_un.S_addr = inet_addr(ip_addr);if (connect(client, (const sockaddr*)&server, sizeof(server)) == SOCKET_ERROR){cout << "Connect Failure!" << endl;break;}char sendmsg[255] = { '\0' };char no[10] = { '\0' };sprintf(no, "%d", i);strcat(sendmsg, "REQ_No.");strcat(sendmsg, no);strcat(sendmsg, " : ");strcat(sendmsg, input.c_str());send(client, sendmsg, 255, 0);char recvmsg[255] = {};recv(client, recvmsg, 255, 0);cout << "Server:" << endl << recvmsg << endl;closesocket(client);}}WSACleanup();return 0;
}

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了