下面将通过这篇文章说明xengine 如何开发http服务,通过此文章 你将学会如何开发一套自己的restful api服务器.而不用第三方服务
下面的演示是基于C C++的版本.你甚至可以用这个库开发一个简单的http服务器
首先,我们需要启动一个Http服务器,下面的代码演示了如何启动一个网络服务器和一个http服务
int main()
{
WSADATA st_WSAData;
WSAStartup(MAKEWORD(2, 2), &st_WSAData);
LPCTSTR lpszMiniFile = _T("./HttpMime.types");
LPCTSTR lpszCodeFile = _T("./HttpCode.types");
if (!RfcComponents_HttpServer_Init(lpszCodeFile,lpszMiniFile))
{
printf("%lX\n", HttpServer_GetLastError());
return 0;
}
if (!NetCore_TCPIocp_StartEx(&xhToken))
{
printf("%lX\n", NetCore_GetLastError());
return 0;
}
NetCore_TCPIocp_RegisterCallBackEx(xhToken, NetCore_CB_Login, NetCore_CB_Recv, NetCore_CB_Close);
CreateThread(NULL, 0, NetCore_Thread, NULL, 0, NULL);
while (1)
{
Sleep(1000);
}
NetCore_TCPIocp_DestroyEx(xhToken);
RfcComponents_HttpServer_Destroy();
WSACleanup();
return 0;
}
启动成功后,你需要在网络回调函数里面为http模块函数设置他们对应的操作,比如下面,有用户连接就为http创建这个用户,用用户离开就关闭这个用户,有用户发送数据就把数据投递给http模块来处理,因为基于TCP流的http服务请求包可能会出现截断等多次发送情况,投递给http模块可以让这个模块帮我们处理各种情况
XNETHANDLE xhToken;
BOOL __stdcall NetCore_CB_Login(LPCSTR lpszClientAddr, SOCKET hSocket, LPVOID lParam)
{
printf("NetCore_CB_Login:%s\n", lpszClientAddr);
RfcComponents_HttpServer_CreateClient(lpszClientAddr);
return TRUE;
}
void __stdcall NetCore_CB_Recv(LPCSTR lpszClientAddr, SOCKET hSocket, LPCSTR lpszRecvMsg, int nMsgLen, LPVOID lParam)
{
printf("NetCore_CB_Recv:%s-%d\n", lpszClientAddr, nMsgLen);
if (!RfcComponents_HttpServer_InserQueue(lpszClientAddr, lpszRecvMsg, nMsgLen))
{
printf("RfcComponents_WSPacket_Post:%lX\n", HttpServer_GetLastError());
}
}
void __stdcall NetCore_CB_Close(LPCSTR lpszClientAddr, SOCKET hSocket, LPVOID lParam)
{
printf("NetCore_CB_Close:%s\n", lpszClientAddr);
RfcComponents_HttpServer_CloseClinet(lpszClientAddr);
}
最后我们需要一个线程来处理http请求,http请求是 请求-应答模式,所以我们处理完一个请求后,需要回复给对方,这里我们返回了一个hello world给对方.
DWORD WINAPI NetCore_Thread(LPVOID lParam)
{
while (TRUE)
{
if (RfcComponents_HttpServer_EventWait())
{
int nMsgLen = 20480;
RFCCOMPONENTS_HTTP_REQPARAM st_ReqParam;
TCHAR tszMsgBuffer[20480];
TCHAR tszClientAddr[64];
list<tstring> stl_ListHdrField;
memset(&st_ReqParam, '\0', sizeof(RFCCOMPONENTS_HTTP_REQPARAM));
memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer));
memset(tszClientAddr, '\0', sizeof(tszClientAddr));
if (RfcComponents_HttpServer_GetRandom(tszClientAddr, &stl_ListHdrField, &st_ReqParam, tszMsgBuffer, &nMsgLen))
{
printf("%s %d:%s\n", tszClientAddr, nMsgLen, tszMsgBuffer);
RFCCOMPONENTS_HTTP_HDRPARAM st_HdrParam;
memset(&st_HdrParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM));
st_HdrParam.bIsClose = TRUE;
st_HdrParam.nHttpCode = 200;
RfcComponents_HttpServer_SendMsg(tszMsgBuffer, &nMsgLen, &st_HdrParam, _T("hello world"), 11);
NetCore_TCPIocp_SendEx(xhToken, tszClientAddr, tszMsgBuffer, nMsgLen);
}
}
Sleep(1);
}
return 0;
}
当然,你可以通过这个函数做更多东西,比如,请求的url可以通过我们的代码得到.一个restful api 服务器需要通过url 和 内容来确定返回什么内容.比如,我们在浏览器里面输入 http://127.0.0.1:5001/api/gethello 服务器会给我们返回hello world 这个就是一个restful api的处理流程
更多的处理流程还可以通过负载json的请求,然后我们通过解析json请求的内容,tszMsgBuffer 就是http 的body 部分,nmsglen 表示tszMsgBuffer 的大小.,通过负载的内容来处理更多内容.我们设置还可以得到http的头字段,stl_ListHdrField 通过这个stl来得到有多少字段然后解析即可.
当然,功能不止这一点,你可以下载后自行研究.