Windows和Linux上均可編譯的簡單HTTP伺服器程式碼

大囚長發表於2018-12-29
/*
此程式碼為一個簡單的HTTP協議伺服器的簡單示例,單執行緒,不具備生產實用性,在Windows 10/Ubuntu 16.04 + VS2017上編譯通過,32位控制檯程式,一直按f5重新整理瀏覽器會造成程式崩潰退出
注意pch.h標頭檔案在編譯Unix系列時要去掉
*/
//非Unix系統
#include "pch.h"
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#define close closesocket
#pragma comment(lib, "ws2_32.lib")

class WinSockInit
{
	WSADATA _wsa;
public:
	WinSockInit()
	{  //分配套接字版本資訊2.0,WSADATA變數地址
		WSAStartup(MAKEWORD(2, 0), &_wsa);

	}
	~WinSockInit()
	{
		WSACleanup();//功能是終止Winsock 2 DLL (Ws2_32.dll) 的使用
	}
};

//Unix系統
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include <iostream>
#include <string>

using namespace std;

//處理URL
void UrlRouter(int clientSock, string const & url)
{
	string hint;
	if (url == "/")
	{
		cout << url << " 收到資訊\n";
		hint = "haha, this is home page!";
		send(clientSock, hint.c_str(), hint.length(), 0);
	}
	else if (url == "/hello")
	{
		cout << url << " 收到資訊\n";
		hint = "你好!";
		send(clientSock, hint.c_str(), hint.length(), 0);
	}
	else
	{
		cout << url << " 收到資訊\n";
		hint = "未定義URL!";
		send(clientSock, hint.c_str(), hint.length(), 0);
	}

}

int main()
{
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
	WinSockInit socklibInit;//如果為Windows系統,進行WSAStartup
#endif

	int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//建立套接字,失敗返回-1
	sockaddr_in addr = { 0 };
	addr.sin_family = AF_INET; //指定地址族
	addr.sin_addr.s_addr = INADDR_ANY;//IP初始化
	addr.sin_port = htons(8090);//埠號初始化

	int rc;
	rc = bind(sock, (sockaddr*)&addr, sizeof(addr));//分配IP和埠

	rc = listen(sock, 0);//設定監聽

	//設定客戶端
	sockaddr_in clientAddr;
	int clientAddrSize = sizeof(clientAddr);
	int clientSock;
	//接受客戶端請求
	while (-1 != (clientSock = accept(sock, (sockaddr*)&clientAddr, (socklen_t*)&clientAddrSize)))
	{
		// 收請求
		string requestStr;
		int bufSize = 4096;
		requestStr.resize(bufSize);
		//接受資料
		recv(clientSock, &requestStr[0], bufSize, 0);

		//取得第一行
		string firstLine = requestStr.substr(0, requestStr.find("\r\n"));
		//取得URL
		firstLine = firstLine.substr(firstLine.find(" ") + 1);//substr,複製函式,引數為起始位置(預設0),複製的字元數目
		string url = firstLine.substr(0, firstLine.find(" "));//find返回找到的第一個匹配字串的位置,而不管其後是否還有相匹配的字串。

		//傳送響應頭
		string response =
			"HTTP/1.1 200 OK\r\n"
			"Content-Type: text/html; charset=gbk\r\n"
			"Connection: close\r\n"
			"\r\n";
		send(clientSock, response.c_str(), response.length(), 0);
		//處理URL
		UrlRouter(clientSock, url);

		close(clientSock);//關閉客戶端套接字
	}

	close(sock);//關閉伺服器套接字

	return 0;
}

相關文章