hpsocket实现HTTP通信功能

2023-05-16

前段时间朋友急需让我帮忙搞定个C++的http库????然后指定了hpsocket这个库。看了一下是国人写了,资料在doc还算比较全,整理了很多框架的部分也挺详细,正好在补基础,所以学习下http后端的一些概念,也学习学习别人的代码。时间比较匆忙,就按照从先从自身的需求出发再到后面可以研究库的源代码思路进行。

这个库是跨平台的,我选择的环境平台是Linux。我的电脑是ubuntu16的

测试demo git

填充

0.目标

作为工作首先要解决的工作:
实现一个HTTP服务,可以实现HTTP收发的功能。

1.编译安装

编译

./compile.sh 

需要把HTTP这选项打开
作者在说明文档中标注了demo/目录不参与这个命令的编译。
demo下的项目都是sln组织的,需要安装和配置Visual C++ for Linux Development插件。
还有部分是编译是通过ndk,这部分也先不管他。
另外这个好像要C++14编译。所以GCC的版本也需要要求5.X以上。

安装

./install.sh

这步我就不装了没啥必要,编译完了就OK了,前面那步会把边的库放在lib目录下

2.实现

实现主要分为两部分:客户端和服务器。服务器是是实现重点。

2.1.服务器

服务器的参考代码我是参考demo/testecho-http的代码。
参考代码中加了命令行控制的代码,看着代码就比较多。这边我把代码重新整理一下,写一个新的demo。新的demo里我就考出了http服务

首先除了库的头文件,包括依赖到一个文件,再demo/gloabl/下的helper.cpp及helper.h。helper.cpp和helper中间包括一些宏定义,配置参数,命令行类之类的,可能还涉及到其他demo中需要的一些宏和定义。

把中间和HTTP有关有用的抽出来放到新建的myhelper.cpp和myhelper.h里。

myhelper.h

首先是包括的头文件

#include 
#include 
#include 
#include 
#include 
#include 

//#include "include/hpsocket/SocketInterface.h"
//#include "include/hpsocket/HPTypeDef.h"
//#include "include/hpsocket/common/GlobalDef.h"
#include "src/common/StringT.h"      
#include "src/HttpServer.h"
#include "src/common/FuncHelper.h"

这里我一开始想用include的库的头文件,发现好多类没有(不过像一些类其实完全可以用自己实现)。这里为了拖原demo方便,就先使用到src源代码的头文件了。不过这里的接口也确实很迷???

然后再试一些服务器参数宏

#define IPV4_LOOPBACK_ADDRESS	_T("127.0.0.1")
#define IPV6_LOOPBACK_ADDRESS	_T("::1")
#define IPV4_ANY_ADDRESS		_T("0.0.0.0")
#define IPV6_ANY_ADDRESS		_T("::")
#define DEF_MULTI_CAST_ADDRESS	_T("233.0.0.1")
#define BROAD_CAST_ADDRESS		_T("255.255.255.255")
#define DEF_TCP_UDP_PORT		5555
#define DEF_HTTP_PORT			8080
#define DEF_HTTPS_PORT			8443

#define TCP_KEEPALIVE_TIME		(60 * 1000)
#define UDP_DETECT_ATTEMPTS		3

...

#define HTTP_NAME				_T("http")
#define HTTPS_NAME				_T("https")
#define STR_HTTP_SCHEMA			"http://"
#define STR_HTTPS_SCHEMA			"https://"
#define CRLF				"\r\n"
#define NV_SEPARATOR_CHAR			'='
#define HEADER_SEPARATOR			": "
#define COOKIE_TOKENIZE			"; "
#define STR_HTTP_1_0			"HTTP/1.0"
#define STR_HTTP_1_1			"HTTP/1.1"
#define HOST_HEADER			"Host"
#define COOKIE_HEADER			"Cookie"
#define SET_COOKIE_HEADER			"Set-Cookie"
#define CONTENT_TYPE_HEADER		"Content-Type"
#define CONTENT_LENGTH_HEADER		"Content-Length"
#define TRANSFER_ENCODING_HEADER	        "Transfer-Encoding"
#define UPGRADE_HEADER			"Upgrade"
#define WEB_SOCKET_HEADER_VALUE		"WebSocket"

#define HTTP_METHOD_POST			"POST"
#define HTTP_METHOD_PUT			"PUT"
#define HTTP_METHOD_PATCH			"PATCH"
#define HTTP_METHOD_GET			"GET"
#define HTTP_METHOD_DELETE			"DELETE"
#define HTTP_METHOD_HEAD			"HEAD"
#define HTTP_METHOD_TRACE			"TRACE"
#define HTTP_METHOD_OPTIONS		"OPTIONS"
#define HTTP_METHOD_CONNECT		"CONNECT"

#define HTTP_WEB_SOCKET_SEC_SALT	        "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

这些不一定全部用到。

参数类:

struct app_arg
{
    static char OPTIONS[];
 CString remote_addr;
 USHORT port;
 CString bind_addr;
 USHORT local_port;
 CString reject_addr;
    ...
 }


这个参数类在原来的demo里其实就是用来存放可执行文件输入动态的参数的。我们这里用不到,用默认值固定它就好了。所以把原程序的几个public方法的定义和实现都去了。然后保留那个全局变量。。。后面就用这个参数

app_arg g_app_arg;

后面会讲到如何使用这个参数,不过这个参数本质就是个容器,用来存放一系列参数。

HTTP相关的类

原demo中对于http的使用顺序是这样的
首先定义一个接口类

class CHttpServerListenerImpl : public CHttpServerListener
{
private:
	virtual EnHandleResult OnPrepareListen(ITcpServer* pSender, SOCKET soListen);
	...
	virtual EnHandleResult OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID);
public:
	CHttpServerListenerImpl(LPCTSTR lpszName): m_strName	(lpszName){}
public:
	CString m_strName;
};

可以看出这个接口类继承于CHttpServerListener。定义再SocketInterface.h中它的描述如下

名称:IHttpServerListener 监听器抽象基类
描述:定义某些事件的默认处理方法(忽略事件)

这个底层其实继承了IHttpListenerT和 ITcpServerListener的接口,也就是http和tcp的接口。这个等后面分析源代码的时候再细讲。

对CHttpServerListenerImpl 类进行实现,这里其实就是TCP和HTTP的几种事件的回调的实现,简单的说就是,发生上面的事件之后会调用对应的函数进行执行。对于每个事件的含义在SocketInterface.h中都有详细的接口说明。这部分的在后面再说。

然后实例化HTTP接口

CHttpServerListenerImpl s_listener_1(HTTP_NAME);
CHttpServerListenerImpl s_listener_2(HTTPS_NAME);

接着创建一个CHttpServer对象,同时绑定到对应的接口

CHttpServer s_http_server(&s_listener_1);
CHttpsServer s_https_server(&s_listener_2);

这里关注下CHttpServer 这个类。整个类会在后面解释,其实这是个库的内部类,不能被调用

typedef CHttpServerT<CTcpServer, HTTP_DEFAULT_PORT> CHttpServer;

是个CHttpServerT的模板类,默认端口是80,另一个参数是CTcpServer的类

template class CHttpServerT : public IComplexHttpResponder, public T
{
	using __super = T;
 public:
     .... //一堆操作接口
 public:
	CHttpServerT(IHttpServerListener* pListener)
	: T					(pListener)
	, m_pListener		(pListener)
	, m_bHttpAutoStart	(TRUE)
	, m_enLocalVersion	(DEFAULT_HTTP_VERSION)
	, m_dwReleaseDelay	(DEFAULT_HTTP_RELEASE_DELAY)
	{}
 ...
}

他的定义可以看出来,继承HTTP的接口类,简单理解为借助CTcpServer功能的实现,绑定前面的接口。所以这个类的对象是对HTTP进行控制管理的关键。

重新回到程序代码中,因为在原有的代码中,程序为了使用的灵活性增加了CHttpCommandParser类,但提取主要功能这部分就不要了。这个类其实就是解析终端输入命令,然后执行不同动作。

fnCmds[CCommandParser::CT_START]	= (CCommandParser::CMD_FUNC)OnCmdStart;
fnCmds[CCommandParser::CT_STOP]		= (CCommandParser::CMD_FUNC)OnCmdStop;
fnCmds[CCommandParser::CT_STATUS]	= (CCommandParser::CMD_FUNC)OnCmdStatus;
fnCmds[CCommandParser::CT_SEND]		= (CCommandParser::CMD_FUNC)OnCmdSend;
fnCmds[CCommandParser::CT_PAUSE]	= (CCommandParser::CMD_FUNC)OnCmdPause;
fnCmds[CCommandParser::CT_KICK]		= (CCommandParser::CMD_FUNC)OnCmdKick;
fnCmds[CCommandParser::CT_KICK_L]	= (CCommandParser::CMD_FUNC)OnCmdKickLong;
fnCmds[CCommandParser::CT_KICK_S]	= (CCommandParser::CMD_FUNC)OnCmdKickSilence;	

动作就是上述几个函数的回调。

整理下我们需要啥:

  1. 启动OnCmdStart
  2. 查看状态OnCmdStatus();
  3. 停止OnCmdStop

好像主要就3步。不过这个是过程非阻塞的,所以我们退出手动控制退出getchar()

int main(int argc, char* const argv[])
{
	s_http_server.SetKeepAliveTime(g_app_arg.keep_alive ? TCP_KEEPALIVE_TIME : 0);
	OnCmdStart();
	OnCmdStatus();
	getchar();
	OnCmdStop();
	return 0;
}

另外可能要先设置下一时间连接时间。原demo里这个先设置了。

这样整个过程就完成了。

接口回调

接着就是接收数据怎么处理了。全部在那几个接口实现的函数里。如果想了解整个过程在每个回调里都打印信息就可以更加直观了解了。

注意:这里需要了解HTTP报文的格式。

然后说一些重点的。(这里之前编译的问题搞来搞去,偷懒我就把都放在myhelper.cpp里了)

/*
* 名称:请求行解析完成通知(仅用于 HTTP 服务端)
* 描述:请求行解析完成后,向监听器发送该通知
*	
* 参数:		pSender		-- 事件源对象
*			dwConnID	-- 连接 ID
*			lpszMethod	-- 请求方法名
*			lpszUrl		-- 请求行中的 URL 域
* 返回值:	HPR_OK		-- 继续执行
*		HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
*/
EnHttpParseResult CHttpServerListenerImpl::OnRequestLine(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)
{
	printf("OnRequestLine: method:%s    url:%s \n", lpszMethod, lpszUrl);
	return HPR_OK;
}

这个函数里面可以得到url然后还有请求参数,请求方法之类的。可以进行解析参数,数据封装之后发给业务处理。

/*
* 名称:请求头通知
* 描述:每当解析完成一个请求头后,向监听器发送该通知
*		
* 参数:		pSender		-- 事件源对象
*			dwConnID	-- 连接 ID
*			lpszName	-- 请求头名称
*			lpszValue	-- 请求头值
* 返回值:	HPR_OK		-- 继续执行
*		HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
*/
EnHttpParseResult CHttpServerListenerImpl::OnHeader(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
{
	printf("OnHeader: 请求头名称:%s 请求头值:%s\n", lpszName, lpszValue);
	return HPR_OK;
}

得到头部信息字段和值,同样按需要获取

/*
* 名称:BODY 报文通知
* 描述:每当接收到 HTTP BODY 报文,向监听器发送该通知
*		
* 参数:		pSender		-- 事件源对象
*			dwConnID	-- 连接 ID
*			pData		-- 数据缓冲区
*			iLength		-- 数据长度
* 返回值:	HPR_OK		-- 继续执行
*			HPR_ERROR	-- 引发 OnParserError() 和 OnClose() 事件并关闭连接
*/
EnHttpParseResult CHttpServerListenerImpl::OnBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	printf("OnBody: size:%d 主体消息: %s\n", iLength, pData);
	return HPR_OK;
}

同样的获得报文主体。

其他还有很多事件的回调处理,具体参考说明

——————————————————————————

发送应答

demo中发送应答在消息完成后(这个其实不一定)

EnHttpParseResult CHttpServerListenerImpl::OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
{
    ...//一堆组发送的内容
    THeader header[] = {{"Content-Type", "text/plain"}, {"Content-Length", strContentLength}, {"Set-Cookie", strSeqCookie1}, {"Set-Cookie", strSeqCookie2}};
	int iHeaderCount = sizeof(header) / sizeof(THeader);
    pSender->SendResponse(	dwConnID,
			HSC_OK,
			"HP Http Server OK",
			header, iHeaderCount,
			(const BYTE*)(LPCSTR)strBody,
			iBodyLength);
	if(!pSender->IsKeepAlive(dwConnID))
		pSender->Release(dwConnID);
	return HPR_OK;
}

前面用了一堆代码组strBody发送整体,这个我没时间整理了。随便改了下,就是发到报文的主体内容变化,不过我demo里是有问题的。
然后就是组织应答报文头部之类的。

2.2.客户端

客户端的实现比较简单甚至都可以不用实现,
大概方法有这么几个:

  • 用demo/Release/下的hp-testecho-http-client.exe可执行程序进行测试
  • curl命令进行测试
  • 浏览器url直接测试

3.编译过程中的问题总结

这个问题出现让我意识到了,真的只能说人丑就要多读书。然后多读书的机会来了。现在趁着有时间好好总结下问题:

代码结构和存放目录
HP-Socket-dev\Linux\mytest
mytest是我新建的目录,里面放着
在这里插入图片描述
关于编译:
我可能是对这个库有误解。一开始直接用g++的命令编译。发现各种未定义的到怀疑人生。没办法就写了makefile

CC = g++ -std=c++14  -w
TARGET = server_test
LDFLAG = -L../lib/hpsocket/x64/
LIBS =  -pthread  -lpthread  -lhpsocket -ldl
CFLAG = -I ../

OBJS = myserver_test.o myhelper.o #$(wildcard /home/awe/HP-Socket-dev/Linux/lib/hpsocket/x64/obj/Release/*.o)

SRC_FILE = myserver_test.cpp myhelper.cpp
 
$(TARGET) : $(OBJS)
	@echo $(CFLAG)
	$(CC) -g $(CFLAG)  $(OBJS) $(LDFLAG) $(LIBS) -o $(TARGET) 

myserver_test.o: myserver_test.cpp
	$(CC) -c $^ -o $@ $(CFLAG)  $(LDFLAG) $(LIBS)

myhelper.o: myhelper.cpp
	$(CC) -c $^ -o $@ $(CFLAG)  $(LDFLAG) $(LIBS)

但是写了makefile后依旧是一堆未引用的问题。

——————————————————————————————————————
其实这个的makefile主要的争议点在哪里呢?
在于链接so库时候的引用的定义。

这里先改回makefile到链接libhpsocket.so库
在这里插入图片描述
列举了一些找不到的引用,但在我的认识中,这些应该都在libhpsocket.so库里的。为什么编译不过。

抱着这个怀疑。我让他直接链接.o文件。将OBJS变量改称如下(就是去掉#):

OBJS = myserver_test.o myhelper.o $(wildcard /home/awe/HP-Socket-dev/Linux/lib/hpsocket/x64/obj/Release/*.o)

然后编译就通过了。。。。也说明libhpsocket.so有问题,同时证明我确实编译了HTTP模块了,因为在编译的时候又让选择是否编译某些模块。

接着我把-lhpsocket去了,发现编译报错,但这次报的是ssl这里的引用错误。这个错误在依赖之内,毕竟我没把依赖库的其他库加进来。这样有说明了个问题,也就是libhpsocket.so确实在工作了。

我甚至都怀疑打包的时候是不是漏掉了某几个.o。然后就改了complish.sh脚本,找到编译生成libhpsocket.so的编译指令。。

g++ -o lib/hpsocket/x64/libhpsocket.so -Wl,--no-undefined -Wl,-Ldependent/x64/lib -Ldependent/x64/lib -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack 
 -shared -Wl,-Bsymbolic -Wl,-soname,libhpsocket.so.5 
 lib/hpsocket/x64/obj/Release/ArqHelper.o 
 lib/hpsocket/x64/obj/Release/BufferPool.o 
 lib/hpsocket/x64/obj/Release/Crypto.o 
 lib/hpsocket/x64/obj/Release/Event.o 
 lib/hpsocket/x64/obj/Release/FileHelper.o 
 lib/hpsocket/x64/obj/Release/FuncHelper.o 
 lib/hpsocket/x64/obj/Release/HPSocket.o 
 lib/hpsocket/x64/obj/Release/HPSocket-SSL.o 
 lib/hpsocket/x64/obj/Release/HPThreadPool.o 
 lib/hpsocket/x64/obj/Release/HttpAgent.o 
 lib/hpsocket/x64/obj/Release/HttpClient.o 
 lib/hpsocket/x64/obj/Release/HttpCookie.o 
 lib/hpsocket/x64/obj/Release/HttpHelper.o 
 lib/hpsocket/x64/obj/Release/http_parser.o 
 lib/hpsocket/x64/obj/Release/HttpServer.o 
 lib/hpsocket/x64/obj/Release/ikcp.o 
lib/hpsocket/x64/obj/Release/IODispatcher.o 
lib/hpsocket/x64/obj/Release/MiscHelper.o 
lib/hpsocket/x64/obj/Release/PollHelper.o 
lib/hpsocket/x64/obj/Release/RWLock.o 
lib/hpsocket/x64/obj/Release/SocketHelper.o 
lib/hpsocket/x64/obj/Release/SSLAgent.o 
lib/hpsocket/x64/obj/Release/SSLClient.o 
lib/hpsocket/x64/obj/Release/SSLHelper.o 
lib/hpsocket/x64/obj/Release/SSLServer.o 
lib/hpsocket/x64/obj/Release/SysHelper.o 
lib/hpsocket/x64/obj/Release/TcpAgent.o 
lib/hpsocket/x64/obj/Release/TcpClient.o 
lib/hpsocket/x64/obj/Release/TcpPackAgent.o 
lib/hpsocket/x64/obj/Release/TcpPackClient.o 
lib/hpsocket/x64/obj/Release/TcpPackServer.o 
lib/hpsocket/x64/obj/Release/TcpPullAgent.o 
lib/hpsocket/x64/obj/Release/TcpPullClient.o 
lib/hpsocket/x64/obj/Release/TcpPullServer.o 
lib/hpsocket/x64/obj/Release/TcpServer.o 
lib/hpsocket/x64/obj/Release/Thread.o 
lib/hpsocket/x64/obj/Release/UdpArqClient.o 
lib/hpsocket/x64/obj/Release/UdpArqServer.o 
lib/hpsocket/x64/obj/Release/UdpCast.o 
lib/hpsocket/x64/obj/Release/UdpClient.o 
lib/hpsocket/x64/obj/Release/UdpNode.o 
lib/hpsocket/x64/obj/Release/UdpServer.o 
-ljemalloc_pic -lz -lssl -lcrypto -lrt -ldl -pthread发现所有的该目录下的所有.o文件都被包括了???????那为啥还不行???????

看看报错的句子然后拿CHttpServerT类进行检测下:

nm libhpsocket.so | grep "CHttpServerT"

发现是有结果的,说明确实被链接进去了,但为什么引不到呢?

但是发现符号的说明基本都是t ,d ,r
查看man说明:t是text段, d是初始化数据段,r是只读数据段。
但在说明里这里有句话非常可疑:

if lowercase, the symbol is usually local; if uppercase, the symbol is global(external).

小写的也就是说这个是本地的符号,大写的是可以给外部用的??

一个是libhpsocket.a的库是可以直接链接的。

nm libhpsocket.a | grep "CHttpServerT"

看到符号基本是W和U.也就是大写的。所以可以调用了

结论:

这个问题现在基本推到libhpsocket.so中的这几个符号是本地符号的问题。

也就是说本质上是因为libhpsocket.so里那个类是个本地类。事实上真正使用的还是IHttpServer这个接口指针,然后获取个这个类用HP_CreateHttpServer的方法

但如何链接成本地符号还是全局符号这个问题还没研究,下次看到整理到动态和和静态库的内容的时候再统一整理下这块。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hpsocket实现HTTP通信功能 的相关文章

  • MPMoviePlayerController 播放 YouTube 视频

    如何在 iPhone 上的 MPMoviePlayerController 中播放 YouTube 视频 同时避免进入全屏模式 这个问题已经在这里提出 MPMoviePlayerController 正在播放 YouTube 视频吗 htt
  • python 2.7 中的 HTTP 2 请求

    在 python 中向 HTTP 1 和 HTTP 2 发出请求有什么区别吗 我可以像这样在 python 中进行 HTTP 1 x 调用 url http someURL values param1 key param2 key2 dat
  • 诸如用于测试 HTTP 请求的虚拟 REST 服务器之类的东西? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我一直在四处寻找 但找不到任何这样的网站 我想知道是否有一些虚拟服务器可以响应测试 GET 请求并返回
  • 404 标头 - HTTP 1.0 还是 1.1?

    为什么我能找到的几乎每个例子 包括这个问题 https stackoverflow com questions 437256 sending a 404 error in php大约一年前 说 404 标头应该是HTTP 1 0 404 N
  • $http.get() 与 JSON 数据

    我正在编写一个服务器应用程序 并希望客户端使用正文中的数据来参数化我的 GET 方法 如下所示 http v GET http localhost 3000 url text 123 foo bar GET url HTTP 1 1 Acc
  • Node.js:server.setTimeout、server.timeout 和 server.keepAliveTimeout 之间有什么区别

    官方文档是here https nodejs org api http html http server settimeout msecs callback server setTimeout 中没有提及有关服务下一个请求的信息 所以我认为
  • 如何在flutter项目中使用http拦截器?

    我必须向我的所有 Api 添加标头 有人告诉我为此使用 http 拦截器 但我无法理解如何做到这一点 因为我是颤振的新手 谁能帮我举个例子吗 您可以使用http 拦截器 https pub dev packages http interce
  • 服务器响应中的“连接:保持活动状态”

    我正在尝试建立从 Silverlight 应用程序到 Apache 服务器托管的 PHP 页面的 HTTP 持久连接 即无需为每个 HTTP 请求创建新的 TCP 连接 为此 我需要网络服务器发送其 HTTP 响应 并将 Connectio
  • 我可以使用 HTTP 范围标头“有意”加载部分文件吗?

    我正在研究 HTTP 范围标头 specs http www w3 org Protocols rfc2616 rfc2616 sec14 html sec14 16 据我了解 我可以设置文件的字节范围ala 0 199 2000 200
  • 从手机访问本地主机[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在使用
  • 使用 flash 或 java servlet 将麦克风数据从浏览器上传到服务器的教程? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 There was a question on how to get data from a microphone on a client
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • put方法中的Angularjs文件上传不起作用

    我有一个简单的待办事项应用程序 我试图在其中上传照片和单个待办事项 现在我已经创建了这个工厂函数来负责待办事项的创建 todosFactory insertTodo function todo return http post baseUr
  • 如何记录进入 IIS 的 HTTP 请求

    我在我的开发机器上运行 IIS 5 我有一个 asp net 3 5 Web 服务在其上运行 我从同一服务器上运行的不同 Web 应用程序调用该服务 我的服务返回错误 500 内部服务器错误 我正在对其进行故障排除 我的请求是通过Syste
  • 流星图像、CSS、“普通”Web 服务

    我经常看到这个问题出现 如何在我的 Meteor 网站上放置图像 如何使用 Meteor 托管 标准 网页内容 我尝试添加一个 img src img myimage png 标签但没有图像显示 如何在 Meteor 站点上托管一些文件 将
  • 这个重写规则是什么意思?

    我正在安装 phpancake 有一个像这样的文件夹 application install library public sql schema install html install php 这条规则意味着什么 RewriteEngin
  • 如何将所有GET请求查询参数放入Go中的结构体中?

    你好 我想将 get 查询参数转换为 Go 中的结构 例如我有这样的结构 type Filter struct Offset int64 json offset Limit int64 json limit SortBy string js
  • Go客户端程序生成大量TIME_WAIT状态的socket

    我有一个 Go 程序 它从多个 goroutine 生成大量 HTTP 请求 运行一段时间后 程序报错 connect cannot allocaterequestedaddress 当检查时netstat 我得到大量 28229 个连接T
  • 如何设置响应文件名而不强制“另存为”对话框

    我在某些响应中返回一个流 设置适当的content type标头 我正在寻找的行为是这样的 如果浏览器能够呈现给定内容类型的内容 那么它应该将其显示在浏览器窗口中 如果浏览器不知道如何呈现内容 那么它应该显示 另存为 对话框 其中文件名应该
  • 以 REST 方式更新整个资源集合

    我有一个资源列表的 REST URI 例如 http foo com group users 这些用户中的每一个都有一个序列号 我想公开一种方法来为集合中的所有用户重新编号这些值 并使访问该列表的每个人都可以使用此更改 由于这是对整个集合的

随机推荐

  • [源码解读]position_estimator_inav_main解读(如何启动光流)

    阅读工具 xff1a source insight 技术交流 xff1a zinghd 64 163 com xff0c 757012902 64 qq com 源码版本 xff1a Firmware xff08 原生固件 xff09 如有
  • C++ 程序编译过程:从代码到程序

    在大学课堂上学习 C 43 43 时 xff0c 老师并没有过多涉猎 C 43 43 语法背后的知识 也就是说 xff0c 初学 C 43 43 时 xff0c 哪怕写出了代码 xff0c 我也并不知道从代码到程序的过程中究竟发生了什么 我
  • 05-STM32F1 - 串行通信1-UART(3),printf,scanf重定向

    05 STM32F1 串行通信UART xff0c printf xff0c scanf重定向 在C 语言标准库中 xff0c fputc 函数是printf 函数内部的一个函数 xff0c 功能是将字符ch 写入到文件指针file所指向文
  • 指针作为函数参数 进行内存释放 并置NULL

    author xff1a 张继飞 写在前面 xff0c 前面写了代码封装free函数 xff0c 但是调用封装并退出后 xff0c 指针并不为NULL xff0c 导致接下来以此作为判断条件的时候就出现问题了 先前封装函数为void fre
  • R40 gpio 寄存器地址操作【原创】

    首先要学会看手册 xff0c 下面拿PC来做说明 3 18 3 Register List Module Name Base Address PIO 0x01C20800 Register Name Offset Description P
  • 关于basic认证和digest认证的初步理解

    1 basic认证是把用户和密码通过base64加密后发送给服务器进行验证 2 digest认证则是把服务器响应的401消息里面的特定的值和用户名以及密码结合起来进行不可逆的摘要算法运算得到一个值 xff0c 然后把用户名和这个摘要值发给服
  • STM32中USART的使用方法

    USART作为一种标准接口在应用中十分常见 本文着重分析其作为 UART的配置和应用方法 1 STM32固件库使用外围设备的主要思路 在 STM32中 xff0c 外围设备的配置思路比较固定 首先是使能相关的时钟 xff0c 一方面是设备本
  • 利用 __FILE__, __LINE__输出debug信息

    include lt stdio h gt define DEBUG ifdef DEBUG define DEBUG format printf 34 File 34 FILE 34 Line 05d 34 format 34 n 34
  • 认证、授权、鉴权和权限控制

    原文地址 https www cnblogs com badboyh2o p 11068779 html 如有侵权 xff0c 请联系删除 xff0c 谢谢 xff01 本文将对信息安全领域中认证 授权 鉴权和权限控制这四个概念给出相应的定
  • 网络编程进阶:并发编程之多线程

    多线程 xff1a 在传统操作系统中 xff0c 每个进程有一个地址空间 xff0c 而且默认就有一个控制线程 xff1b 进程的作用就是隔离数据 进程只是用来把资源集中到一起 xff08 进程只是一个资源单位 xff0c 或者说资源集合
  • subprocess 使用执行 cmd

    参考 Python模块之subprocess用法实例详解 腾讯云开发者社区 腾讯云 上面这个链接主要说了一些用法 补充 通用示例 先来看一个的用法 xff0c 执行 ls 命令 xff0c 返回结果 xff0c 没有报错 xff0c 执行完
  • 多旋翼无人机小知识

    https blog csdn net np4rHI455vg29y2 article details 78954871 根据牛顿第三定律 xff0c 旋翼在旋转的同时 xff0c 也会同时向电机施加一个反作用力 xff08 反扭矩 xff
  • RTK

    实时动态技术 xff08 英语 xff1a Real Time Kinematic xff0c RTK xff09 是实时动态载波相位差分技术的简称 xff0c 是一种通过基准站和流动站的同步观测 xff0c 利用载波相位观测值实现快速高精
  • github Tags和Branch分支相关操作(三)

    Tag推送 1 git查看tag命令 xff1a git tag 2 创建Tag直接加入名字就好了 xff0c 格式 xff1a git tag 名字 m 注释 这时只能在本地可以看到自己新建Tag xff0c 在远程中央仓库中还是看不到在
  • PostMan中文汉化亲测好用!!!!

    PostMan 中文汉化版 最新版本 xff1a 8 10 0 更新时间 xff1a 2021 08 07 请认真阅读存储库的自述文件README md 汉化包下载链接 https github com hlmd Postman cn re
  • ubuntu下安装多个版本的python

    本身系统安装了python2 7和python3 5 现在由于开发需要 xff0c 还需要安装python3 6 安装步骤如下 xff1a 1 下载 Python 直接在官网下载 Python的源代码 xff0c 解压缩 xff0c 按照
  • stm32标准库文件内容说明

    目录 思维导图 一 stm32f4xx h文件内容说明 1 定义了HSE时钟频率的值 2 定义了启动HSE时钟的超时时间 xff0c HSI时钟频率的值 3 根据不同的芯片定义中断向量表结构体 4 包含一些头文件 5 对一些数据类型进行重命
  • UART协议详解

    UART使用的是 异步 xff0c 串行通信 串行通信是指利用一条传输线将资料一位位地顺序传送 特点是通信线路简单 xff0c 利用简单的线缆就可实现通信 xff0c 降低成本 xff0c 适用于远距离通信 xff0c 但传输速度慢的应用场
  • C++中的.和::和:和-」的区别

    转自 xff1a https blog csdn net liao392781 article details 97931845 在学习C 43 43 的过程中我们经常会用到 和 和 xff1a 和 gt xff0c 在此整理一下这些常用符
  • hpsocket实现HTTP通信功能

    前段时间朋友急需让我帮忙搞定个C 43 43 的http库 xff1f xff1f xff1f xff1f 然后指定了hpsocket这个库 看了一下是国人写了 xff0c 资料在doc还算比较全 xff0c 整理了很多框架的部分也挺详细