linux 一个简单的WEB服务器

以下程序经过测试使用,对简单的html和图片显示均有效
//============================================================================
// Name        : netServers.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include<error.h>
#include <cstring>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
using namespace std;

const char PATH[]="/home/user";                   //指定一个你自己的www目录

    void *recvMsg(void *param) 
   {

    int fd2 = *(int*) param;     //客户端的sockid
    char buf[1024];
    char exname[100];
    int len;
     if(recv(fd2, buf, sizeof(buf), 0)>0) {  
        len=strlen(buf);
        cout<<"收到 一个 请求,浏览器端发来的请求内容为:"<<endl<<buf<<endl;
               if(strstr(buf,"Accept: ")!=NULL)      //获取浏览器发送的http请求中的内容类别
               {
                   char *pp=strstr(buf,"Accept: ");
                   char *p1=strchr(pp,' ');
                   char *p2=strchr(pp,',');
                   strncpy(exname,p1+1,p2-p1-1);
               }
        cout<<"name:"<<exname<<endl;         //输出text/html或image/png
        if (strncmp(buf, "GET",3) == 0) {
            char webname[100];
            char *p1=strchr(buf,' ');
            char *p2=strchr(p1+1,' ');
            strncpy(webname,p1+1,p2-p1-1);       //获取浏览器请求的文件名
                        cout<<webname;
            struct stat st;
            char filename[1024]={'\0'};
            strcpy(filename,PATH);
            strcat(filename,webname);
            stat(filename,&st);
            char protol[2048]={'\0'};
            char content_type[100]={'\0'};
            if(strncmp(webname,"/sword.jpg",10)==0)               //随便指定一个图片文件
            {
                strncpy(content_type,"Content-Type: image/jpeg\r\n",strlen("Content-Type: image/jpeg\r\n"));
            }else
            {
                strncpy(content_type,"Content-Type: text/html\r\n",strlen("Content-Type: text/html\r\n"));
            }
            sprintf(protol,"HTTP/1.1 200 OK\r\n"
                    "Server: Apache-Coyote/1.1\r\n"
                    "ETag: \"W/6381-1144994988000\"\r\n"
                    "Last-Modified: Fri, 14 Apr 2006 06:09:48 GMT\r\n"
                    "%s"
                    "Content-Length: %d bytes\r\n"
                    "Date: Mon, 19 Jun 2011 07:21:09 GMT\r\n"
                    "Connection: keep-alive\r\n\r\n",content_type,(int)st.st_size);
            cout<<protol<<endl;
            send(fd2,protol,strlen(protol),0);                  //此处调了好久,刚开始是使用sizeof(protol),有问题,响应头没那么多内容
            size_t len=0;
            char fbuf[1024]={'\0'};   
                        const char*filename2="/home/user/sword2.jpeg";
                        int fd4=open(filename2,O_WRONLY|O_CREAT,0777);
            int fd=open(filename,O_RDONLY,0777);
            while((len=read(fd,fbuf,sizeof(fbuf)))>0){
                send(fd2,fbuf,len,0);

                                write(fd4,fbuf,len);
            }
            close(fd);
                        close(fd2);
        }
    }
        pthread_exit(NULL);
    return NULL;
}

int main() {
    int fd;
    struct sockaddr_in serveraddr;
    struct sockaddr_in clientaddr;
    memset(&serveraddr, 0, sizeof(serveraddr));

    while ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        cout << "socket failed!" << endl;
    }
    int reuser=1;
    setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuser,sizeof(reuser));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(8080);          //端口号指定为:8080
    serveraddr.sin_addr.s_addr = inet_addr("192.168.0.234");//htonl(INEADDR_ANY);     //指定你自己的IP
    socklen_t len = sizeof(serveraddr);

    if (bind(fd, (const sockaddr*)&serveraddr, len)< 0) {
        cout << "bind error" << endl;
        return 0;
    }
    int ret = listen(fd, 5);
    if (ret != 0) {
        cout << "listen error" << endl;
        return 0;
    } else {
        cout << "listening......" << endl;
    }
    while(1){
        socklen_t size=sizeof(clientaddr);
        int fd2 = accept(fd,(struct sockaddr*)&clientaddr, &size);
        if (fd2==-1) {
            cout << "accept failed" << endl;
            return 0;
        }
                cout<<inet_ntoa(clientaddr.sin_addr)<<endl;
        pthread_t id1;
        pthread_create(&id1,NULL,recvMsg,&fd2);
    }
      close(fd);
      return 0;
}



简单的 测试index.html代码(放在你的主目录www目录中):
<HTML>
<HEAD><title>test</title></head>
<BODY bgcolor="white">
<center><p><h1>welcome!<h1></p>
<p>Hello,I am Navy!!!</p>
<img src='http://changfengmingzhi.blog.163.com/blog/sword.jpg'/>
<img src='http://changfengmingzhi.blog.163.com/blog/sword.jpg'/>
</center>
</BODY>
</HTML>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值