标准C语言实现简单Web服务器(注意:暂未解决更改端口号的问题)

目录一、设计目标二、相关技术三、设计内容3.1需求分析3.2概要设计3.3详细设计(主要函数分析)3.3.1(socket)3.3.2(bind)3.3.3(listen)3.3.4(accept)3.3.5(connect)一、设计目标完成基础的tcp连接,支持基础的client与其连接使用fork()来支持并发访问服务器简单的http访问,支持静态页面访问,需要一定的报错机制,如404页面的建立。socket实现简单Http服务器,完成html的解析;运行该服务器可以通过浏览器访问服务器目录
摘要由CSDN通过智能技术生成

一、设计目标

完成基础的tcp连接,支持基础的client与其连接使用fork()来支持并发访问服务器简单的http访问,支持静态页面访问,需要一定的报错机制,如404页面的建立。

  1. socket实现简单Http服务器,完成html的解析;
  2. 运行该服务器可以通过浏览器访问服务器目录下的 Html文件、jpg图片、css文件的载入,完成初步的Http服务器功能。

二、相关技术

Server端:

  1. 完成socket(),bind(),listen()这些初始化工作后,调用accept()方法阻塞等待(其实就是进入一个死循环),等待CLient的connect()方法连接 Client端;

  2. 先调用socket(),然后调用connect()想要与Server端进行连接,这个时候就会进行传说中的TCP三次握手,也就是在Client 发起connect(),并且Server进入accept()阻塞等待时发生三次握手。

在这里插入图片描述

图1 三次握手

Client:浏览器

三、设计内容

3.1需求分析

Web服务器使用HTTP协议与客户端(即浏览器)通信,而HTTP协议又基于TCP/IP协议。浏览器输入地址后,首先和web服务器建立tcp连接,然后浏览器发送http请求报文, web服务器响应处理这个报文,再给他回复一个响应,然后服务器主动断开连接。实现服务器与客户端间的通信。可以实现HTTP请求中的GET方法。
还可供静态网页浏览功能,如可浏览:HTML页面,无格式文本,常见图像格式等,还可以检查一些明显错误报告给客户端,如:403无权访问,404找不到所请求的文件,501不支持相应方法等。在服务器端可输出HTTP响应的相关信息。服务器端可配置参数,如:主目录,首页文件名,HTTP端口号等项。

3.2概要设计

在这里插入图片描述

图2 TCP流程图

代码概要:
(1)加载协议栈
(2)创建监听套接字,用于监听客户请求
(3)创建服务器地址:IP+端口号
(4)绑定监听套接字和服务器地址
(5)通过监听套接字进行监听
(6)接受客户端的连接请求,返回与该客户建立的连接套接字
(7)创建线程接受浏览器请求

3.3详细设计(主要函数分析)

3.3.1(socket)

套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的lP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。
流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP协议。
socket()函数用于根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源。

WSADATA wsdata;                                              
//先确定socket版本信息,WSADATA是一种结构体,存放windows socket初始化信息                             
	
int isok = WSAStartup(MAKEWORD(2, 2), &wsdata);              
	//WSAStartup为异步套接字启动函数,用来指定版本号及获取特定的细节
第一个参数:需要版本号,MAKEWORD是制造一个short类型,高字节表示小版本号,低字节表示主版本号,第二个参数:传出参数,用来获取信息。

SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   
//创建一个socket(定义一个SOCKET类型的名为server的变量),第一个参数:协议族,决定了socket的地址类型(AF_INET表示用Ipv4),第二个参数:传输类型,SOCK_STREAM表示流传输,第三个参数:指定传输协议,IPPROTO_TCP表示使用tcp协议。
3.3.2(bind)

将一本地地址与一套接口捆绑。本函数适用于未连接的数据报或流类套接口,在connect()或listen()调用前使用。当用socket()创建套接口后,它便存在于一个名字空间(地址族)中,但并未赋名。bind()函数通过给一个未命名套接口分配一个本地名字来为套接口建立本地捆绑(主机地址/端口号)。

//初始化协议地址,绑定ip和端口号
	 struct sockaddr_in seraddr;                                  
//自定义sockaddr_in结构体,定义服务端
seraddr.sin_family = AF_INET;
//sin_family指代协议族,为socket函数第一个参数AF_INET(Ipv4)
	 seraddr.sin_port = htons(80);
//sin_port存储端口号,80端口服务于HTTP,网络中的数据和电脑上的数据存储是有区别的,必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字
	 seraddr.sin_addr.s_addr = (INADDR_ANY); 
//sin_addr存储IP地址,INADDR_ANY表示可监听任意绑定了80端口的ip地址
 	 isok = 
  • 12
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值