基于C++编写的简单web服务器

来源:互联网 发布:美国人知乎 编辑:程序博客网 时间:2024/04/28 11:19

基于c++编写的简单web服务器程序

 使用vs2012编程软件

 

程序执行流程;

1、创建一个ServerSocket对象;

2调用ServerSocket对象的accept方法,等待连接,连接成功会返回一个Socket对象,否则一直阻塞等待;

3Socket对象中获取InputStreamOutputStream字节流,这两个流分别对应request请求和response响应;

4处理请求:读取InputStream字节流信息,转成字符串形式,并解析,这里的解析比较简单,仅仅获取uri(统一资源标识符)信息;

5处理响应:根据解析出来的uri信息,从WEB_ROOT目录中寻找请求的资源资源文件,读取资源文件,并将其写入到OutputStream字节流中;

6关闭Socket对象;

7转到步骤2,继续等待连接请求;

 

将要请求的html文件放置到工程目录下

 

打开IE  指定地址端口号  请求文件index.html

浏览器显示:

 

 

服务器端:

 

 

附源代码:

#include <cstdlib>

#include <iostream>

 

#include <conio.h>

#include <stdio.h>

#include <winsock2.h>

#include <string.h>

#include <fstream>

#pragma comment(lib,"Ws2_32.lib")

 

bool InitSocket();

int endsWith(char s1[],char s2[]);

 

using namespace std;

 

int main(int argc,char *argv[])

{

    struct sockaddr ser_addr,client_addr;

    int off;

    bool over;

    char msg[1003];

    char msgtp[450];

    SOCKET welcomesock ;

 

    if( !InitSocket() ) return 0;//初始化Window Sockets DLL(ws2_32.dll)

        

    welcomesock = socket(AF_INET,SOCK_STREAM,0 ); //创建流Socket:即传输层使用TCP

 

    if( welcomesock==INVALID_SOCKET ){//不能创建,返回

        printf("不能创建Socket!");

        getch();

        WSACleanup( );//卸载Window Sockets DLL

        return 0;

     }

     

    //设置服务器IP地址和端口号

   ((sockaddr_in*)&ser_addr)->sin_family = AF_INET;//AF_INET:使用Internet 协议

   ((sockaddr_in*)&ser_addr)->sin_port = htons(3000); //服务器端口号3000

   ((sockaddr_in*)&ser_addr)->sin_addr.s_addr = inet_addr("127.0.0.1");//主机地址

 

    //把套接字与地址绑定

    bind(welcomesock,&ser_addr,sizeof(ser_addr));

    

    //监听网络连接

    listen(welcomesock,5);//监听连接:1--允许等待队列的长度

  

    printf("等待客户连接!\n");

  

    while(true)

    {int len;

      struct sockaddr client_addr;

       len =sizeof(client_addr);

      //接受网络连接,生成新的套接字sersock标识这一连接

      SOCKET connectsock = accept( welcomesock,&client_addr,&len );

      //从等待队列中检取客户,如队列空则进程挂起

      //如不空,则接受并生成新Socket以表示此连接,而原Socket继续等待新客户

      if(connectsock==INVALID_SOCKET){

         DWORD err = WSAGetLastError();

         char txt[100];

         sprintf(txt,"error when accept!---errno:%d",err);

         printf(txt);

         getch();

         WSACleanup( );//卸载Window Sockets DLL

         return 0;

       }

     

       printf("有客户连接!\n等待用户信息\n");

     

       len = recv ( connectsock,msg,1000,0 );//接收请求行

       

      /* if(len>=1000&&msg[len-1]!='\n'&&msg[len-2]!='\r')

       {

           printf("%d\n",len);

           len=recv ( connectsock,msgtp,400,0 );

       }*/

       msg[len]=0;  //char msg[1003]

       printf(msg);

       printf("\n");

       

       char * p;

     

       p = strtok(msg," ");   //分割函数

       

       if(strcmp(strupr(p),"GET")==0)  //strupr()用于将字符串中的字符转换为小写   strcmp()函数:比较字符串(区分大小写)

       {

          p = strtok(NULL," ");    

          if(p[0]=='/')

          {

              p=p+1;

          }

           char * fname; //定义读入文件名

           int flen,hlen;

           int textflag=0;

           

           fname=p;

           ifstream fin(fname,ios::binary);//打开准备读取的文件

 

           char sentence[2048]={0};//定义文件读写的变量

           if(fin.good())  //good()表示文件流是否正常,eof表示文件流是否到结束了

           {

              char tp[40];

              

              fin.seekg(0,ios::end);//基地址为文件结束处,偏移地址为0,于是指针定位在文件结束处

              flen= fin.tellg();  //tellg()函数不需要带参数,它返回当前定位指针的位置,也代表着输入流的大小。

              fin.seekg(0,ios::beg);  //表示输入流的开始位置

              

              strcpy(sentence,"HTTP/1.1 200 OK\r\n");

              strcat(sentence,"Content-Length: ");//把两个字符串连接起来

              sprintf(tp,"%d",flen);  //格式化输出字符串

              strcat(sentence,tp);

              

              strcat(sentence,"\r\nContent-Type: ");

              if(endsWith(fname,".html")||endsWith(fname,".htm"))

              {  strcpy(tp,"text/html");

                 textflag=1;

                }

              else

              {   if(endsWith(fname,".txt"))

                  {  strcpy(tp,"text/plain"); textflag=1;     }

                  else

                  {   if(endsWith(fname,".jpg"))

                      {  strcpy(tp,"image/jpeg\r\nAccept-Ranges:bytes");   }

                      else

                      {if(endsWith(fname,".gif"))

                        { strcpy(tp,"image/gif");}

                      }

                  }

              }

              strcat(sentence, tp);

              strcat(sentence,"\r\n");

              strcat(sentence,"\r\n");

              

              printf(sentence);

              int s;

              s=send ( connectsock,sentence,strlen(sentence),0 );//connectsock发送端套接字字符串描述  sentence存放应用程序要发送数据的缓冲区  strlen(sentence)要发送字节数

            

              

              char ft[1024]={0};

              int i,j;

              if(textflag==0)

              {

                  while(!fin.eof())

                  {                   

                      fin.read(ft,sizeof(ft));

                     

                    send ( connectsock,ft,sizeof(ft),0 );

                      

                  }                  

              }

              else

              {

                  

                  while(fin.getline(ft,1024))

                  {

                      send ( connectsock,ft,strlen(ft),0 );

                    }

                 

              }

                

            }

         else

            printf("can not open the file!");

       

       }

   

      printf("\n\n已返回处理结果!\n");

     

     //关闭套接字

      closesocket(connectsock);

      printf("\n已关闭与该客户的连接!\n");

      printf("\n等待下一客户连接!\n");

 

    }

    closesocket(welcomesock);

  

    WSACleanup( );//卸载Window Sockets DLL

    return 0;

}

 

bool InitSocket()

{

    WORD wVersionRequested;

    WSADATA wsaData;

    int err;

 

    wVersionRequested =MAKEWORD( 2, 0 );

    //初始化Windows Sockets DLL,

    err = WSAStartup( wVersionRequested, &wsaData );//加载Winsock DLL到内存

    if ( err != 0 ) {

        printf("没有Windows Socket动态库!\n");

        getch();

        return false;

     }

 

    if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 ) {

        printf("需要Windows Socket 2!\n");

        getch();

        WSACleanup( );//非winsock 2.0时,卸载Window Sockets DLL

        return false;

    }

    return true;

}

int endsWith(char s1[],char s2[])

{  

  int len1 = strlen(s1);  

  int len2 = strlen(s2);  

  int i=len1-1,j=len2-1;  

  if(len1<len2)return 0;  

  for(;i>=0&&j>=0;i--,j--){  

    if(s1[i]!=s2[j])return 0;  

  }  

  return 1;  

}  

 

0 0
原创粉丝点击