8、简单Web Server程序的设计与实现

一、设计题目

8、简单Web Server程序的设计与实现

二、设计内容

实现一个简单的 Web Server,能够响应客户端的请求将指定目录下的 HTML 或 text 件通过指定的TCP 端发送给客户端。具体编程要求是:

  (1)服务器启动时可指定服务端口,默认为 8000

  (2)可指定 Web Server 的根目录。

  (3)服务器应能够并发处理多个请求。要求至少能支持 Get 命令。鼓励增强 Web Server 的功能,如支持 HeadPost 以及 Delete 等命令

  (4)统计 Web Server 接收和发送的流量。

  (5)在 Windows 平台实现,要求使用图形界面显示服务器的各种信息。

  (6)不允许使用已有的 HTTP 库。

  (7)编写必要的客户端测试程序用于发送 HTTP 请求并显示返回结果,也可使用一般的 Web 浏览器测试。

三、设计步骤

3.1原理分析

HTTP 协议工作流程:

1.首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP 的工作就开始了。

2.建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息:包括请求修饰符、客户机信息和可能的内容。

3.服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息包括服务器信息、实体信息和可能的内容。

4.客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。  

3.2编程设计

案例的设计步骤:

Web Server 可以分为两个组成模块:客户请求处理模块响应生成发送模块。其中客户请求处理模块的任务就是负责接收客户的连接,它监听系统的端口,以获取客户机到达本服务器的连接,在程序中线程 ListenThread 实现该部分功能。当获得一个连接请求时,就为该连接建立一个客户请求处理线程来处理这个请求,请求处理线程就是响应生成发送模块负责分析请求中的各个协议参数,根据客户请求的分析结果查找资源,生成响应和发送响应,在程序中线程 ClientThread 实现该部分功能。

数据结构

#define BUFFER_SIZE 1024     //缓冲区大小

#define HOST "192.168.43.253"  //IP地址

#define PORT 8100           //端口

#define HEADER "\          //构造请求头

HTTP/1.1 200 OK\r\n\

Content-Type: text/html; charset=UTF-8\r\n\

Server: ZYhttp_v1.0.1\r\n\

Content-Length: %ld\r\n\r\n\

"

关键代码

1)读取文本

        ifstream fin(strPath.c_str(), ios::in | ios::binary);

        if (fin.is_open())

        {

            memset(buffer, 0, BUFFER_SIZE);

            //每次读取一个字节

            while (fin.read(buffer, BUFFER_SIZE - 1))

            {

                if (send(socketClient, buffer, strlen(buffer), 0) < 0)

                {

                    printf("发送数据失败!");

                    break;

                }

                memset(buffer, 0, BUFFER_SIZE);

            }

            if (send(socketClient, buffer, strlen(buffer), 0) < 0)

            {

                printf("发送数据失败!");

                break;

            }

        }

2)获取文件长度

long GetFileLength(string strPath)

{

    ifstream fin(strPath.c_str(), ios::in | ios::binary);

    fin.seekg(0, ios_base::end);

    streampos pos = fin.tellg();//返回当前文件位置

    long lSize = static_cast<long>(pos);

    fin.close();

    cout<<"content:"<<lSize<<endl;

    return lSize;

}

程序流程图

四、调试过程

浏览器地址栏进行数据输入,分析数据传输的形式,一开始没搞明白。后来加深了认识。

五、结果及分析

往浏览器输入指定的IP地址及端口号,按F12进入控制台,查看数据传输情况。

                 8,WebServer Result

       8,WebServer IP地址

六、心得体会、

  随着最后一个课设题目的完成,对计算机网络的认识愈发清晰。不再是此前那种只存在于书本上的知识点,而是实实在在的、解决千家万户的网络相关问题的方案的集合,与生活并不遥远。

#include <cstdio>
#include <string>
#include <fstream>
#include <WinSock2.h>
#include <iostream>
using namespace std;
#define BUFFER_SIZE 1024
#define HOST "192.168.43.253"
#define PORT 8100
#define HEADER "\
HTTP/1.1 200 OK\r\n\
Content-Type: text/html; charset=UTF-8\r\n\
Server: ZYhttp_v1.0.1\r\n\
Content-Length: %ld\r\n\r\n\
"
const string strPath = "Web Server\bin\Debug\1.html";
#pragma comment(lib, "WS2_32")
// 获取文件的大小
long GetFileLength(string strPath);
// 单线程函数
int main(int argc, char **argv)
{
    // 定义并且初始化一个服务器套接字
    sockaddr_in addrServer;
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.S_un.S_addr = INADDR_ANY;
    addrServer.sin_port = htons(PORT);
    // 初始化
    WSADATA wsaData;
    WORD socketVersion = MAKEWORD(2, 2);
    if (WSAStartup(socketVersion, &wsaData) != 0)
    {
        printf("初始化失败!");
        exit(1);
    }
    // 创建套接字
    SOCKET socketServer = socket(AF_INET, SOCK_STREAM, 0);
    if (socketServer == SOCKET_ERROR)
    {
        printf("创建失败!");
        exit(1);
    }
    // 绑定服务器套接字
    if (bind(socketServer, (LPSOCKADDR)&addrServer, sizeof(addrServer)) == SOCKET_ERROR)
    {
        printf("绑定失败!");
        exit(1);
    }
    // 监听
    if (listen(socketServer, 10) ==  SOCKET_ERROR)
    {
        printf("监听失败!");
        exit(1);
    }
    while (true)
    {
        printf("Listening ... \n");
        sockaddr_in addrClient;
        int nClientAddrLen = sizeof(addrClient);
        //服务器端建立连接
        SOCKET socketClient = accept(socketServer, (sockaddr*)&addrClient, &nClientAddrLen);
        if (SOCKET_ERROR == socketClient)
        {
            printf("接收失败!");
            break;
        }
        char buffer[BUFFER_SIZE];
        memset(buffer, 0, BUFFER_SIZE);
        //接收数据
        if (recv(socketClient, buffer, BUFFER_SIZE, 0) < 0)
        {
            printf("接收数据失败!");
            break;
        }
        printf("接收到的数据 : \n%s", buffer);
        // response
        // send header
        memset(buffer, 0, BUFFER_SIZE);
        sprintf(buffer, HEADER, GetFileLength(strPath));//把文件和头文件合并然后发送数据
        if (send(socketClient, buffer, strlen(buffer), 0) < 0)
        {
            printf("发送数据失败!");
            break;
        }
        //读取文本
        ifstream fin(strPath.c_str(), ios::in | ios::binary);
        if (fin.is_open())
        {
            memset(buffer, 0, BUFFER_SIZE);
            //每次读取一个字节
            while (fin.read(buffer, BUFFER_SIZE - 1))
            {
                if (send(socketClient, buffer, strlen(buffer), 0) < 0)
                {
                    printf("发送数据失败!");
                    break;
                }
                memset(buffer, 0, BUFFER_SIZE);
            }
            if (send(socketClient, buffer, strlen(buffer), 0) < 0)
            {
                printf("发送数据失败!");
                break;
            }
        }
        //printf("发送!");
        //关于网络连接与数据传递
        fin.close();
        closesocket(socketClient);
    }
    closesocket(socketServer);
    WSACleanup();
    return 0;
}

long GetFileLength(string strPath)
{
    ifstream fin(strPath.c_str(), ios::in | ios::binary);
    fin.seekg(0, ios_base::end);
    streampos pos = fin.tellg();//返回当前文件位置
    long lSize = static_cast<long>(pos);
    fin.close();
    cout<<"content:"<<lSize<<endl;
    return lSize;
}

### 回答1: 简单Web服务器程序可以通过以下步骤进行设计实现: 1. 确定服务器的基本功能和需求,例如支持的HTTP方法、文件类型、请求处理方式等。 2. 选择合适的编程语言和框架,例如Python的Flask框架、Java的Spring框架等。 3. 设计服务器的路由和请求处理逻辑,包括URL映射、请求参数解析、业务逻辑处理等。 4. 实现服务器的静态文件服务,即能够处理静态文件的请求并返回相应的文件内容。 5. 实现服务器的动态内容服务,即能够根据请求参数生成动态内容并返回相应的内容。 6. 添加必要的安全措施,例如防止SQL注入、XSS攻击等。 7. 进行测试和调试,确保服务器的稳定性和可靠性。 以上是简单Web服务器程序设计实现的基本步骤,具体实现过程还需要根据具体需求和技术栈进行调整和优化。 ### 回答2: 随着互联网和计算机的不断发展,简单web server程序设计实现变得越来越重要。下面就来探讨一下如何进行简单web server设计实现。 I. 设计 1.考虑web server的基本功能 Web server的基本功能包括解析客户端的HTTP请求、读取静态资源文件(如HTML、JS、CSS、图片等)、响应客户端请求、记录日志等。在设计中需要考虑这些基本功能,并从中找到各个部分之间的联系,从而设计出一个高效的web server程序。 2.确定web server的开发语言 在设计时需要选择一个适合的编程语言进行开发,例如Java、C++、Python、Go等。需要根据自己的实际需求和对技术的掌握程度来选择。不同编程语言有着不同的特点和优点,可以根据自己的实际情况来进行选择。 3.确定web server的架构 Web server的架构是设计的核心部分,需要考虑到众多因素。常见的web server架构有单线程架构、多线程架构和异步架构。需要根据自己的实际需求来进行选择,如单线程架构适用于并发请求数较低的情况;多线程架构适用于并发请求数较高的情况;异步架构适用于I/O密集型的场景。需要根据实际场景进行选择。 II. 实现 1. 创建Socket 建立服务器需要一个监听的Socket,将它绑定到一个IP地址和端口号,这样服务器就可以监听到客户端的连接请求。 2. 接受请求 将监听Socket放在死循环中不断监听客户端的请求,一旦有客户端请求连接,就创建一个新的Socket进行通信。 3. 解析请求和响应 解析客户端请求的HTTP报文,提取出其中的资源文件路径和方法信息、用户信息等。根据请求信息,读取相应的资源文件,将其内容返回给客户端,并且进行HTTP状态响应码、Cookie设置、Header信息添加等操作。 4. 记录日志 在服务端记录日志,可以通过输出流的方式将日志信息写入文件或者控制台中。日志信息通常包括客户端IP地址、请求的资源文件路径、请求时间等信息。 以上就是简单web server程序设计实现流程,当然还有很多需要考虑的因素,如安全方面的考虑、性能优化等。实现过程中还需要注意一些问题,如线程安全、多用户连接等问题,需要经过严谨的测试确保服务器程序稳定可靠。 ### 回答3: 简单web server程序是一种基于HTTP协议的服务器程序,能够接收来自客户端的请求,并将相应的内容返回给客户端。实现一个简单web server可分为以下几个步骤: 1. 确定需要支持的HTTP协议版本,常用的有HTTP/1.0和HTTP/1.1。为了与客户端建立连接,需要使用TCP协议。 2. 监听端口:web server需要在计算机上的一个端口上监听客户端请求。通常情况下,web server监听标准端口80。如果想要使用其他端口号,也需要在客户端提供访问时指定相应的端口号。 3. 解析HTTP请求:当客户端发送请求时,将触发web server的相应事件。服务器需要解析HTTP请求的报文头部,获得请求的URL、请求方法和协议版本等信息。常见的请求方法有GET和POST。 4. 处理请求:web server需要根据请求的URL路径找到相应的资源,并利用相应的程序对请求进行处理。对于静态资源,服务器可以直接读取文件返回给客户端,对于动态资源,则需要通过调用脚本等程序进行计算,再将结果返回给客户端。 5. 构建HTTP响应:web server需要构建HTTP响应,并将其发送给客户端。在响应中需要包含状态码、响应头和响应实体等信息。常见的状态码有200表示成功,404表示资源不存在等。 6. 关闭连接:当响应发送完成后,服务器需要将TCP连接关闭,释放资源。 从上述步骤可以看出,实现一个简单web server需要考虑很多细节。为了简化操作,可以使用现成的web框架,如Python的Flask、Java的Spring等,这些框架已经实现了许多功能,只需要简单的配置即可开发web应用。同时,为了保证web server的安全性和稳定性,还需要考虑并发处理、错误处理、安全认证等问题。因此,实现一个高性能、安全的web server仍然需要专业的开发人员来完成。
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值