IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 8、简单Web Server程序的设计与实现 -> 正文阅读

[网络协议]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;

}

程序流程图

创建流式套接字s

Bind(),套接字s与本地相连

Listen(),为客户连接创建等待队列

创建ListenThread线程,接收客户机连接要求

Accept(),接收等待连接,返回相应连接的套接字cs

创建ClientThread线程,处理客户机request

程序是否结束?

Closesocket(),关闭最初套接字s,结束ListenThread线程

Y

N

四、调试过程

浏览器地址栏进行数据输入,分析数据传输的形式,一开始没搞明白。

后来加深了认识。

五、结果及分析

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

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;
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 23:16:55  更:2021-07-14 23:17:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/29 9:39:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码