C语言实现简单HTTP 服务器

C语言实现简单HTTP 服务器

日常工作中,使用java的springboot框架开发controller接口很方便,如果使用C语言开发一个controller接口该如何实现呢?本文使用C语言基于socket网络编程提供一个样例仅供参考。

开发平台: windows Microsoft Visual Studio Community 2022

#include <stdio.h>
#include <winsock2.h>
#include <string.h>
#include <io.h>
 
#pragma comment(lib, "ws2_32.lib")
 
/*
* 网络编程  包含头文件:  winsock2.h
*           引用库文件:  ws2_32.lib
*/
 
 
char rev_buffer[1024];	//接收信息缓冲区
char filePath[128];		//网页文件路径
 
 
/**
* 主要步骤:
* 1.初始化网络库
* 2.创建socket
* 3.绑定IP地址和端口号
* 4.监听连接
* 5.接收连接
* 6.处理连接请求
* 7.关闭连接,关闭网络库
**/
 
 
int main()
{
 
	//============================================================================
	//1.初始化网络库  WSA --> Windows Socket API
	//para1:指定socket版本  使用最新的2.2版本即可
	//para2:是一个传出参数
 
	int ret;
	WSADATA wsadata;
 
	ret = WSAStartup(MAKEWORD(2, 2), &wsadata);
	if (ret != 0)
	{
		printf("WSADATA启动失败\r\n");
		exit(-1);
	}
	else
	{
		printf("WSADATA启动成功\r\n");
	}
 
	//============================================================================
	//2.创建socket
	//para1:指定IP协议  AF_INET -> IPV4  AF_INET6 -> IPV6
	//para2:数据传输格式  常用的有两种:流式传输(TCP)  数据包传输(UDP)
	//para3:传输协议:
 
	SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (serverSocket == INVALID_SOCKET)
	{
		printf("创建serverSocket失败\r\n");
		exit(-1);
	}
	else
	{
		printf("创建serverSocket成功\r\n");
	}
 
	//============================================================================
	//3.绑定IP地址和端口号(对于服务器是绑定,对于客户端是连接)
	//para1:  指定socket
	//para2:  IP地址和端口号
	//para3:  para2的长度
 
	SOCKADDR_IN serverAddr;
	serverAddr.sin_family = AF_INET;//必须和创建socket时一样
	serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;
	serverAddr.sin_port = htons(80);//此处涉及到大端存储和小端存储    一般计算机上都是小端的 网络上一般都是大端的  所以需要将本地字节序转为网络字节序
 
	ret = bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
	if (ret == SOCKET_ERROR)
	{
		printf("套接字绑定失败\r\n");
		exit(-1);
	}
	else
	{
		printf("套接字绑定成功\r\n");
	}
 
	//============================================================================
	//4.监听连接
 
	listen(serverSocket, 10);
	printf("服务器监听中......\r\n");
 
	//============================================================================
	//5.接收连接
 
	SOCKADDR clientAddr;
	int len_clientAddr = sizeof(clientAddr);
 
	while (1)
	{
		SOCKET clientSocket = accept(serverSocket, &clientAddr, &len_clientAddr);
		if (clientSocket == INVALID_SOCKET)
		{
			printf("建立客户端连接失败\r\n");
			exit(-1);
		}
		else
		{
			printf("成功建立客户端连接\r\n");
		}
 
		//6.处理连接请求
		//从clientSocket接受数据
 
		ret = recv(clientSocket, rev_buffer, sizeof(rev_buffer), 0);
		printf("The return of recv is:%d\r\n", ret);
 
		if (ret <= 0)
		{
			printf("接收来自客户端的数据失败\r\n");
			printf("重新进入等待连接状态......\r\n");
			closesocket(clientSocket);
			continue;
			//exit(-1);
		}
		else
		{
			printf("成功接收来自客户端的数据:\r\n");
			printf("%s\r\n", rev_buffer);
		}
 
		//给客户发送网页	后续可以根据具体请求,转向不同页面
		strcpy(filePath, "index.html");
 
		ret = access(filePath, 0);//0 代表判断文件是否存在  如果存在返回0 否则返回-1
		if (ret != 0)
		{
			//未找到文件
			char sendBuf[1024] = { 0 };
 
			sprintf(sendBuf, "HTTP/1.1 404 NOT FOUND\r\n");
			send(clientSocket, sendBuf, strlen(sendBuf), 0);
 
			sprintf(sendBuf, "Content-type:text/html\r\n");
			send(clientSocket, sendBuf, strlen(sendBuf), 0);
 
			sprintf(sendBuf, "\r\n");
			send(clientSocket, sendBuf, strlen(sendBuf), 0);
 
 
			sprintf(sendBuf, "找不到,滚!!!!\r\n");
			send(clientSocket, sendBuf, strlen(sendBuf), 0);
		}
		else
		{
			//找到相关网页文件
			FILE* fs = fopen(filePath, "r");
			if (fs == NULL)
			{
				printf("打开网页文件失败\r\n");
				exit(-1);
			}
			else
			{
				char dataBuf[1024] = { 0 };
 
				sprintf(dataBuf, "http/1.1 200 success\r\n");
				send(clientSocket, dataBuf, strlen(dataBuf), 0);
 
				sprintf(dataBuf, "content-type:text/html\r\n");
				send(clientSocket, dataBuf, strlen(dataBuf), 0);
 
				sprintf(dataBuf, "\r\n");
				send(clientSocket, dataBuf, strlen(dataBuf), 0);
 
				do
				{
					fgets(dataBuf, 1024, fs);
					send(clientSocket, dataBuf, strlen(dataBuf), 0);
				} while (!feof(fs));
 
				fclose(fs);
			}
		}
		closesocket(clientSocket);//发送完直接关闭  因为HTTP协议是无连接的
	}
 
	//7.关闭连接,清理网络库
 
	closesocket(serverSocket);
	WSACleanup();
 
	return 0;
}

然后浏览器访问localhost:8000,页面返回结果:
在这里插入图片描述

visualStudio控制台输出结果如下:
在这里插入图片描述

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简易的Web服务器C语言实现代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define MAX_BUFFER_SIZE 1024 #define SERVER_PORT 8080 int main(int argc, char *argv[]) { int server_sock, client_sock; struct sockaddr_in server_addr, client_addr; char buffer[MAX_BUFFER_SIZE]; // 创建TCP套接字 server_sock = socket(AF_INET, SOCK_STREAM, 0); if (server_sock == -1) { perror("socket"); exit(EXIT_FAILURE); } // 设置服务器地址和端口 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); // 绑定套接字到服务器地址和端口 if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("bind"); exit(EXIT_FAILURE); } // 监听客户端连接 if (listen(server_sock, 5) == -1) { perror("listen"); exit(EXIT_FAILURE); } printf("Server is listening on port %d\n", SERVER_PORT); while (1) { socklen_t client_addr_len = sizeof(client_addr); // 接受客户端连接请求 client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len); if (client_sock == -1) { perror("accept"); continue; } printf("Client %s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); // 接收客户端请求 int bytes_received = recv(client_sock, buffer, MAX_BUFFER_SIZE, 0); if (bytes_received == -1) { perror("recv"); close(client_sock); continue; } // 处理客户端请求,这里简单地将请求内容返回给客户端 if (send(client_sock, buffer, bytes_received, 0) == -1) { perror("send"); } close(client_sock); printf("Client %s:%d disconnected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); } close(server_sock); return 0; } ``` 以上代码使用了Socket API来实现TCP套接字的创建、绑定、监听、接受连接、接收请求、处理请求、发送响应和关闭连接等功能。实际上,要实现一个完整的Web服务器,还需要考虑多线程、文件读取、错误处理等方面的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值