原创 Maye426 C语言Plus 2020-06-12收录于话题#C语言图形界面项目练习10个

1简易版web服务器开发

在计算机逐步渗入社会生活各个层面的今天,计算机已经成为人们日常生活的一分,越来越多的人使用计算机办公、娱乐等等。

[源码分享]网络编程之简易web服务器,编程就是如此简单_C语言本篇主要为为了实现WEB服务器,运行自己写的服务器之后,在浏览器地址栏输入127.0.0.1即可访问网页,注意只能单个网页文件哦~

[源码分享]网络编程之简易web服务器,编程就是如此简单_C语言_02

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