socket 多线程http服务器

利用windows socket实现http服务器。

暂时只实现了http 的get请求。

服务器源码:

#define  _WINSOCK_DEPRECATED_NO_WARNINGS  
#include <winsock2.h>   
#include<iostream>  
#include<string>  
#include<thread>  
#include<fstream>
#include<sstream>

#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll    

#define BUF_SIZE 10086  
//直接用std好像会出现bug  
using std::cout;
using std::endl;
using std::thread;
using std::string;
using std::stringstream;			//字符串流,方便处理字符串
using std::ifstream;				//文件流,进行文件操作

//因为socket实际上是int变量,故可直接返回int  
int make_socket(int port)
{
	//初始化dll  
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//创建套接字    
	SOCKET servSock = socket(AF_INET, SOCK_STREAM, 0);

	//绑定套接字    
	sockaddr_in sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充    
	sockAddr.sin_family = PF_INET;  //使用IPv4地址    
									//sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //回送IP地址   
	sockAddr.sin_addr.s_addr = INADDR_ANY;          //服务器直接默认本地ip  
	sockAddr.sin_port = htons(port);  //端口    
	bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

	//进入监听状态    
	listen(servSock, 20);
	return servSock;
}

void handle_accept(int socket_feed)
{
	cout << "线程为:" << std::this_thread::get_id() << std::endl;
	char buf[1024] = { '\0' };
	string cmd;
	string filename;
	recv(socket_feed, buf, sizeof(buf), 0);
	stringstream sstream;//2
	cout << buf;
	sstream << buf;
	sstream >> cmd;
	sstream >> filename;
	cout << cmd << " " << filename << endl;
	//string head = "HTTP/1.0 200 OK\r\nContent - type:text/html\r\n\r\n";
	//send(socket_fd, head.c_str(), strlen(head.c_str()), 0);
	//send(socket_fd, buf, strlen(buf), 0);
	if (cmd == "GET")
	{
		ifstream file;
		filename = filename.substr(1, filename.length() - 1);
		file.open(filename, ifstream::binary);
		string head = "HTTP/1.0 200 OK\r\nContent - type:text/plain\r\n\r\n";
		//检查文件是否存在
		if (!file)
		{
			cout << "fail" << endl;
			closesocket(socket_feed);
			return;
		}
		if (filename.find(".html") != string::npos || filename.find(".htm") != string::npos)
		{
			head = "HTTP/1.0 200 OK\r\nContent - type:text/html\r\n\r\n";
		}
		if (filename.find(".png") != string::npos)
		{
			head = "HTTP/1.0 200 OK\r\nContent - type:image/png\r\n\r\n";
		}
		if (filename.find(".jpg") != string::npos)
		{
			head = "HTTP/1.0 200 OK\r\nContent - type:image/jpg\r\n\r\n";
		}
		send(socket_feed, head.c_str(), strlen(head.c_str()), 0);
		//传输文件
		while (!file.eof())
		{
			char buf[1024] = { '\0' };
			memset(buf, 0, sizeof(buf));
			file.read(buf, sizeof(buf) - 1);
			int n = file.gcount();
			send(socket_feed, buf, n, 0);
		}
		file.close();
	}
	closesocket(socket_feed);
}

int main() {
	int servSock = make_socket(10086);
	while (true)
	{
		int socket_feed = accept(servSock, nullptr, nullptr);
		thread t(handle_accept, socket_feed);
		t.detach();         //分离线程  
	}

	//终止 DLL 的使用    
	WSACleanup();

	return 0;
}


1.首先编译运行服务器代码。


2.在服务器exe文件所在的目录下随便放置一个html文件


3.在浏览器中输入http://localhost:你设置的端口号/你放置的文件名。然后就可以访问该网页了   


遇到的坑:

一定不能在IDE(比如VS2015)中直接编译运行源代码,否则判断请求文件是否存在的那一行会一直gg,即打开文件失败。因为此时IDE的指针(应该可以这么形容吧),已经指向了被请求文件。而该文件不能同时被两个指针同时操作。

所以应该手动打开编译好的exe文件。

想法:
感觉对http的理解加深了一些,自己感觉,其实http协议就是对TCP传输过来的数据的一个包装。例如传输的数据为010101000110010......01010。我们可以将其理解为字符串——”hello word“。我们也可以将其理解为一张图片。。。。。。总之对一串二进制代码的解释会有n种。而http协议就相当于约定了一种大家都认可的对010101000110010......01010的解释。

总而言之,TCP传输010101000110010......01010的比特串,而http负责解释它。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值