一个简单的Http服务器 - Go语言中文社区

一个简单的Http服务器


               

计算机网络的课程设计代码,使用基本的socket编写的,采用多线程处理访问

写了 一下午,本来想把php链进来,结果之后就不想碰了~~~委屈

环境是 VS2010

主要是两个类:

HttpServer:用来创建监听
response:用来响应请求
能够处理GET 和 POST报文
只是因为没有后台的脚本语言处理,所以把请求参数显示在了控制台的界面上
完整的代码和可运行程序在github~~~~~
  class HttpServer  {  public:   int PORT;   string HTTP_FILE;   string stopsymbol;   WSAData wsadata;   HttpServer(int a):PORT(a)   {}   void start();   void stop();    static void make_response(SOCKET s,char *buffer,int len)  {    response res(s,string(buffer));    map <string, string>::iterator m1_Iter;    for ( m1_Iter=res.value.begin();m1_Iter!=res.value.end();m1_Iter++)    cout<<m1_Iter->first<<"  : "<<m1_Iter->second<<endl;;  }  static  bool GetAddressBySocket(SOCKET m_socket,SOCKADDR_IN &m_address)//读取IP和Port  {   memset(&m_address, 0, sizeof(m_address));   int nAddrLen = sizeof(m_address);   if(::getpeername(m_socket, (SOCKADDR*)&m_address, &nAddrLen) != 0)   {    printf("Get IP address by socket failed!n");    return false;   }   //cout<<"IP: "<<::inet_ntoa(m_address.sin_addr)<<"  PORT: "<<ntohs(m_address.sin_port)<<endl;   return true;  }  static DWORD WINAPI AnswerThread(LPVOID lparam)  {  int len = 0;    char buffer[SIZE_BUFFER];   SOCKET  ClientSocket=(SOCKET)(LPVOID)lparam;  memset(buffer,0,SIZE_BUFFER);   if((len = recv(ClientSocket,buffer,SIZE_BUFFER,0))>0){    SOCKADDR_IN ad;    GetAddressBySocket(ClientSocket,ad);    cout<<"from  "<<::inet_ntoa(ad.sin_addr)<<"  request for: ";    make_response(ClientSocket,buffer,len);   //printf("%s",buffer);    //send(ClientSocket, protocolHead,strlen(protocolHead),0);   }    return 1;   }  };

#include "StdAfx.h"#include "server.h"void HttpServer::start(){ stopsymbol=""cout<<"start service successful"<<endl; WSAStartup(MAKEWORD(2,0),&wsadata);   SOCKET ssocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建一个TCP的Socket,但是没有绑定   struct sockaddr_in server;   server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //inet_addr("192.168.1.107");   server.sin_family = AF_INET;   server.sin_port = htons(PORT);//创建一个端口地址,指定地址和端口号       if(bind(ssocket,(sockaddr*)&server,sizeof(sockaddr_in)) == SOCKET_ERROR) {    std::cout<<"error bind"<<std::endl;   }//绑定TCP Socket到指定的端口地址   if(listen(ssocket, 4) == SOCKET_ERROR) {    std::cout<<"listen error"<<std::endl;   }   fd_set read_fdset;//读文件描述符   std::vector<int> sockets;//读端口的集合,每监听到一个请求,就会新建一个端口,并且存放到该集合中   HANDLE       hThread; DWORD        dwThreadId;  SOCKET       sClient;  while(true){    if (stopsymbol=="stop")  {   closesocket(ssocket);   break;  }  FD_ZERO(&read_fdset);    FD_SET(ssocket,&read_fdset);   int n = select(0,&read_fdset,NULL,NULL,0);    if(FD_ISSET(ssocket,&read_fdset))  {//如果监听端口接收到了读的请求,也就是客户端发起了请求连接     SOCKET sClient = accept(ssocket,NULL,0);//创建一个新的端口    if(n!=SOCKET_ERROR)   {      hThread=CreateThread(NULL,NULL,HttpServer::AnswerThread,(LPVOID)sClient, 0, &dwThreadId);    //if(hThread==NULL)       // printf("CreatThread AnswerThread() failed./n");    //else    // printf("CreateThread OK./n");       }    }   }  }void HttpServer::stop(){ stopsymbol="stop"cout<<"stop service successful"<<endl;}


response类:
#ifndef __RESPONSE_H_#define __RESPONSE_H_#include <string>#include <winsock2.h>#include <stdio.h>#include <iostream>#pragma comment(lib,"ws2_32.lib")#include <vector>#include <fcntl.h>#include <map>#include <fstream>#include <string>using namespace std;const string src("a");class response{publicstring response_code; SOCKET s; string request; int Content_Length; vector<string> line_request; map<string,string> value; string Content_Type; string file; string extension; string Connection; string Server; void work() {  fstream f;  string sss=src+file;  cout<<file<<endl;  f.open(sss,ios::in);  if(!f)  {   response_code="HTTP/1.1 404 Not Found";   output_header("a/404.html");   output_file("a/404.html");   f.close();   return;  }  response_code="HTTP/1.1 200 OK";  if (extension=="php")  {   //sss=phps::make_php(sss);  }  output_header(sss.c_str());  output_file(sss.c_str());  f.close(); } void output_header(const char *f) {  int length;  ifstream is;  is.open (f, ios::binary);  is.seekg (0, ios::end);  length = is.tellg();  length+=2;  char pp[25];  itoa(length,pp,10);  string contentlength="Content-Length: "+string(pp)+"rn";  string temp=response_code+"rn"+Server+"rn"+contentlength+"Content-Type: "+Content_Type+"rn"          +Connection+"rn";  char *bufs=new char[ temp.length() + 1 ];  strcpy( bufs,temp.c_str());  int len=temp.length();  sendall(s,bufs,&len); } void output_file(const char* f) {   FILE* read_from;    int readed = -1;      read_from = fopen(f, "rb");    if(read_from != NULL)    {           char read_buf[128];        //读文件时的字节缓存数组   send(s, "rn", 2, 0);      //再加一个"rn" 不能缺少 格式要求   while(!feof(read_from))    {      //判断文件是否已经结束    fread(read_buf, 16,8, read_from);   //读取    int len = sizeof(read_buf);    if (sendall(s, read_buf, &len) == -1)     { //发送数据     printf("Sending error!");    //出现发送错误显示到控制台继续发送     continue;    }   }  }   closesocket(s);  //send(s, "rn", 2, 0);  } static int sendall(int s, char *buf, int *len)    {   //cout<<buf;  int total = 0;           // 已经发送字节数  int bytesleft = *len;                                   //还剩余多少字节  int n=0;  while(total < *len)   {   n = send(s, buf+total, bytesleft, 0);   if (n == -1) { break; }   total += n;   bytesleft -= n;  }  *len = total;           // 返回实际发送出去的字节数  return n==-1?-1:0;          // 成功发送返回0 失败-1  } static vector<string> split(string& str,const char* c) {  char *cstr, *p;  vector<string> res;  cstr = new char[str.size()+1];  strcpy(cstr,str.c_str());  p = strtok(cstr,c);  while(p!=NULL)  {   res.push_back(p);   p = strtok(NULL,c);  }  return res; } response(SOCKET ss,string a) {  s=ss;  request=a;  line_request=split(request,"n");  //for (int i=0;i<line_request.size();i++)  // cout<<line_request[i]<<endl;  Server="Server: DHS/1.0";  Connection="Connection: close";  if (line_request[0][0]=='G' || line_request[0][0]=='g')  {   make_get_request();  } else  if (line_request[0][0]=='P' || line_request[0][0]=='p')  {   make_post_request();  } else  make_bad_request();  work(); } void make_bad_request(){}; void make_post_request() {  vector<string> content=split(line_request[0]," ");  string vv;  int ct;  for (int i=0;i<line_request.size();i++)   if(line_request[i].substr(0,14)=="Content-Length")   {    ct=atoi(line_request[i].substr(15,string::npos).c_str());    break;   }  //cout<<ct<<endl;  file=content[1];  if (file.length()==1 && file[0]=='/')   file="/index.html";  int position=request.find_first_of("nn");  if (position==string::npos)   position=request.find_first_of("rnrn");  vv=request.substr(request.length()-ct,ct);  vector<string> v=split(vv,"&");  //cout<<vv<<endl;  for (int i=0;i<v.size();i++)  {   int p=v[i].find('=');   value[v[i].substr(0,p)]=v[i].substr(p+1,v[i].length()-p-1);  }  extension="";  for (int i=file.length()-1;i>=0;i--)  {   if (file[i]=='.')    {    extension=file.substr(i+1,file.length()-i-1);    break;   }  }  //map <string, string>::iterator m1_Iter;  //for ( m1_Iter=value.begin();m1_Iter!=value.end();m1_Iter++)  // cout<<m1_Iter->first<<"  "<<m1_Iter->second<<endl;  if (extension=="jpg" || extension=="jpeg" || extension=="jpe")   Content_Type = "image/jpeg";   else if (extension=="gif")   Content_Type = "image/gif";   else if (extension=="png")   Content_Type="image/png";   else if (extension=="pdf")   Content_Type="application/pdf";   else Content_Type="text/html"; }; void make_get_request() {  vector<string> content=split(line_request[0]," ");  vector<string> con;  if (content[1].find('?')!=string::npos)  {   con=split(content[1],"?");   if (con[1].length()>0)   {    vector<string> v=split(con[1],"&");    for (int i=0;i<v.size();i++)    {     int p=v[i].find('=');     value[v[i].substr(0,p)]=v[i].substr(p+1,v[i].length()-p-1);    }   }   file=con[0];  } else   file=content[1];  if (file.length()==1 && file[0]=='/')   file="/index.html";  extension="";  for (int i=file.length()-1;i>=0;i--)  {   if (file[i]=='.')    {    extension=file.substr(i+1,file.length()-i-1);    break;   }  }  //map <string, string>::iterator m1_Iter;  //for ( m1_Iter=value.begin();m1_Iter!=value.end();m1_Iter++)  // cout<<m1_Iter->first<<"  "<<m1_Iter->second<<endl;  if (extension=="jpg" || extension=="jpeg" || extension=="jpe")   Content_Type = "image/jpeg";   else if (extension=="gif")   Content_Type = "image/gif";   else if (extension=="png")   Content_Type="image/png";   else if (extension=="pdf")   Content_Type="application/pdf";   else Content_Type="text/html";   }};#endif


           

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_44943626/article/details/89735612
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 19:55:27
  • 阅读 ( 1063 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢