原创 Maye426 C语言Plus 2020-06-12收录于话题#C语言图形界面项目练习10个
1简易版web服务器开发
在计算机逐步渗入社会生活各个层面的今天,计算机已经成为人们日常生活的一分,越来越多的人使用计算机办公、娱乐等等。
本篇主要为为了实现WEB服务器,运行自己写的服务器之后,在浏览器地址栏输入127.0.0.1即可访问网页,注意只能单个网页文件哦~
2 背景知识
客户端与服务器基于TCP协议建立联系,用HTTP协议访问Web服务器
欢迎提交主题,提供更多文章示例~~
web服务器设计原理:第一步,创建socket套接字;
第二步,bind绑定IP地址和端口号;
第三步,listen监听连接;
第四步,accept取出已经建立好的连接;
第五步,recv读客户端发送的数据,send发送数据给客户端。
3 错误及解决方案
此程序使用vs 2019+easyx开发。
刚开始学习C语言或者没接触过easyx的伙伴,拿到代码之后肯定有很多的错误,这就是所谓的给了源码也不能运行,所以配置环境和查看报错也是作为编程学习者,必须要掌握的技能。
vs安装使用教程:[点击查看教程]
easyx安装使用教程:[点击查看教程]
拿到代码提示很多错误解决方案:[点击查看教程]
4. 话不多说上代码
先看代码,然后自己去敲代码练习哦~网页文件可以点击阅读原文获取
#include<stdio.h>
#include<WinSock2.h>
#include<WS2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
void SendHtml(SOCKET s, char *filename);
int merror(int redata,int error,char *showinfo)
{
if (redata == error)
{
perror(showinfo);
printf("\n");
getchar();
return -1;
}
return 1;
}
int main()
{
printf("-----欢迎使用顽石老师Web服务器...\r\n");
WSADATA wsdata;//1,确定socket版本信息
//第一个参数:需要版本号,MAKEWORD是制造一个short类型,高字节表示小版本号,低字节表示主版本号
//第二个参数:传出参数,用来获取信息
int isok=WSAStartup(MAKEWORD(2, 2), &wsdata);//异步套接字启动函数,用来指定版本号及获取特定的细节
merror(isok, WSAEINVAL, "socket请求失败");
//2,创建一个socket
//第一个参数:协议族,决定了socket的地址类型(AF_INET表示用Ipv4)
//第二个参数:传输类型,SOCK_STREAM 流传输 其他:帧传输
//第三个参数:指定传输协议,IPPROTO_TCP 使用tcp协议
SOCKET server=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
merror(server, INVALID_SOCKET, "socket创建失败");
//3.初始化协议地址,绑定ip和端口号
struct sockaddr_in seraddr;
seraddr.sin_family = AF_INET;//指定协议族,必须和socket函数第一个参数一样
seraddr.sin_port = htons(80);//注意:网络中的数据和电脑上的数据存储是有区别的,网络是大端存储(高存底),pc小端(高存高)
seraddr.sin_addr.s_addr = INADDR_ANY;//监听任意ip地址,只要是绑定了80端口就行
isok = bind(server,&seraddr ,sizeof(seraddr));
merror(isok, SOCKET_ERROR, "绑定信息失败");
//4,监听客服端 //第一个参数,谁监听,第二个,监听最大数量,排队举例
isok=listen(server, 5);
merror(isok, SOCKET_ERROR, "监听失败");
struct sockaddr_in claddr;
int cllen=sizeof(claddr);
while (1)
{
printf("正在等待连接中...\n");
/*第一个参数表示谁接受连接
第二个参数表示是谁连接进来了(服务端连接到了,需要知道连接的是谁,不然无法通信)
第三个参数表示用来保存信息的结构体的大小
注意:第2,3个参数可以不写,但是不写无法保存客户端信息
返回值为链接进来的客户端的socket*/
SOCKET client = accept(server, &claddr, &cllen);
merror(client, INVALID_SOCKET, "连接失败");
printf("连接成功...\n");
//printf("连接成功...%s\n",inet_ntoa(claddr.sin_addr));
char recvdata[1024] = "";
//inet_ntoa 把网络字节序,转为点分十进制
//第一个参数:接受从哪来的消息 第二个参数:接受消息的指针
//第三个参数:接受消息的指针内存大小 第四个参数:0表示默认的收发方式,一次都收完,等待流传输完成之后一次收取
recv(client, recvdata, sizeof(recvdata), 0);
printf("%s 共收到%d字节数据~\n\n", recvdata, strlen(recvdata));
//char senddata[1024] = "<h1 style=\"color:red;\">你好,我是顽石老师,你是谁!</h1>";
//send(client, senddata, strlen(senddata), 0);
char *filename = "./index.html";
SendHtml(client, filename);
closesocket(client);
}
closesocket(server);//关闭服务器socket
WSACleanup();//关闭套接字请求
while (1);
return 0;
}
void SendHtml(SOCKET s,char *filename)
{
FILE *pfile=fopen(filename, "r");
if (pfile == NULL)
{
printf("文件打开失败");
return;
}
char tempdata[1024] = "";
do
{
fgets(tempdata, 1024, pfile);
send(s, tempdata, strlen(tempdata), 0);
} while (!feof(pfile));
}