mirai-cpp icon indicating copy to clipboard operation
mirai-cpp copied to clipboard

Connect 失败

Open tiemoxishi opened this issue 2 years ago • 20 comments

mirai-core 版本 2.7.0 mirai-api-http 版本:2.0.2 mirai-cpp 版本 2.0.2 目前的情况是调试跟踪在执行Connect函数时可以成功获取到sessionKey,但是在执行pmem->eventClient.Connect时的返回文本中显示了404,如果忽略这个问题也无法接收到事件响应,请问这个是我环境哪里出了问题吗?

tiemoxishi avatar Sep 16 '21 00:09 tiemoxishi

找到了解决方法,原来是需要在mirai-api-http的配置文件中这样去写

adapters: - http - ws

不过还有一件事情想请问一下,在最新版本中未提供判断是否登录成功的API,如何判断指定BOT是否已上线?

tiemoxishi avatar Sep 16 '21 08:09 tiemoxishi

找到了解决方法,原来是需要在mirai-api-http的配置文件中这样去写

adapters:

  • http
  • ws

不过还有一件事情想请问一下,在最新版本中未提供判断是否登录成功的API,如何判断指定BOT是否已上线?

mirai没有登录的bot,应该是无法Connect的。 登录之后掉线是有相关事件的,你可以通过On函数监听到。

cyanray avatar Sep 16 '21 09:09 cyanray

11

现在出现了这样的一个情况,mirai-cpp已经connect成功,但是无法获取事件,这个情况应该如何排查问题呢? 现在connect代码已经修改成这样了,不过需要提醒一下,我之前出现的那个情况,没有在mirai-http-api中开启ws时connect不会投递异常

do
{
	try
	{

		pBOT->Connect(opts);
		break;
	}
	catch (const std::exception& ex)
	{
		std::this_thread::sleep_for(1s);
	}
}
while (true);

tiemoxishi avatar Sep 16 '21 12:09 tiemoxishi

11

现在出现了这样的一个情况,mirai-cpp已经connect成功,但是无法获取事件,这个情况应该如何排查问题呢? 现在connect代码已经修改成这样了,不过需要提醒一下,我之前出现的那个情况,没有在mirai-http-api中开启ws时connect不会投递异常

do
{
	try
	{

		pBOT->Connect(opts);
		break;
	}
	catch (const std::exception& ex)
	{
		std::this_thread::sleep_for(1s);
	}
}
while (true);

具体是哪些事件无法收到? 可以在这一行插断点,如果收到事件就会进入断点。 如果没有进入断点,说明 WebSocket 部分没有工作。 可能原因有:

  1. mah 没开启 ws,修改 mah 配置文件开启 ws 就好了;
  2. 掉线了,监听 LostConnection 事件并使用 bot.ReConnect 重连就好了;
  3. 事件处理函数阻塞了,无法退出,导致线程池枯竭了(线程池大小可通过 SessionOptions 设置)
  4. 一些冷门的事件,mirai-cpp 写错了

cyanray avatar Sep 16 '21 12:09 cyanray

这是我的代码,如果connect会跳出循环,输出login successful,我是用一个程序控制多个bot,不知道这样写是否可以?(在之前的版本是可以的,我之前使用的是1.x的版本,昨天所有QQ全部提示使用非官方版本QQ冻结了,所以更新至最新版本)

for (auto& v : robot_list)
{
	std::thread([v] {

	MiraiBot* pBOT = new MiraiBot;
	g_umapBOT[v.strUser] = pBOT;
	SessionOptions opts;
	// 使用 Set 函数赋予值
	opts.BotQQ.Set(QQ_t(std::stoull(v.strUser)));
	opts.EnableVerify = false;
	opts.HttpPort = 8769;
	opts.WebSocketPort = 8769;
	
	fmt::print("{} login start\n", v.strUser);
	do
	{
		try
		{
	
			pBOT->Connect(opts);
			break;
		}
		catch (const std::exception& ex)
		{
			std::this_thread::sleep_for(1s);
		}
	}
	while (true);
	fmt::print("{} login successful\n", v.strUser);
	
	//好友
	pBOT->On<Message>(
		[&](Message m)
		{
			if (m.GetMessageType() == MessageType::FriendMessage || m.GetMessageType() == MessageType::TempMessage)
			{
				g_msgProcessor.OnProcessorPrivateMsg(m);
			}
		});
	getchar();
	
	}).detach();
}

tiemoxishi avatar Sep 16 '21 12:09 tiemoxishi

getchar();

有没有可能是 getchar(); 阻塞了标准输出。去掉试试。 你的 MiraiBot 对象是 new 出来的,只要不主动 delete,就不会触发析构函数,所以可以不阻塞。

cyanray avatar Sep 16 '21 12:09 cyanray

依然还是不行的,没有阻塞标准输出的,因为多数BOT可以接收到事件并且输出内容,我现在把getchar();也去掉了,还是不行。 另外我发现还有一个情况,我在这里打印输出的bot qq每次打印的全部都是相同的,可以确定输出信息时BOTQQ肯定不是输出的那个。

tiemoxishi avatar Sep 16 '21 13:09 tiemoxishi

依然还是不行的,没有阻塞标准输出的,因为多数BOT可以接收到事件并且输出内容,我现在把getchar();也去掉了,还是不行。 另外我发现还有一个情况,我在这里打印输出的bot qq每次打印的全部都是相同的,可以确定输出信息时BOTQQ肯定不是输出的那个。

你的问题是否已解决,如果没有解决,我最近可能会在线程安全方面对 mirai-cpp 进行检查,我也不确定它是不是线程安全的。

cyanray avatar Sep 22 '21 14:09 cyanray

没有解决哦,最终我换回了1.x版本。 我出现问题的环境是使用mcl最新版本,登录多个bot,mirai-cpp都可以connect成功,但是只能收到一个bot的事件,由于时间原因我没有检查到底是mirai-http-api的问题,还是mirai-cpp的问题。

tiemoxishi avatar Sep 22 '21 14:09 tiemoxishi

我怀疑在MiraiBot里面有部分不是线程安全的(

misaka-20002 avatar Oct 27 '22 12:10 misaka-20002

可以试试这样 在调用前单线程初始化所有的miraibot对象 然后再创建对应的thread

misaka-20002 avatar Oct 27 '22 12:10 misaka-20002

我怀疑在MiraiBot里面有部分不是线程安全的(

几乎都不是线程安全的,MiraiBot 类的 API 主要取决于那个HTTP库,那个库应该不是线程安全的。 还有 MessageChain 是基于 STL 实现的,STL 不是线程安全的,所以它也不是线程安全的。(凭印象的回答,我很久没看这个库的代码了)

cyanray avatar Oct 27 '22 12:10 cyanray

我怀疑在MiraiBot里面有部分不是线程安全的(

几乎都不是线程安全的,MiraiBot 类的 API 主要取决于那个HTTP库,那个库应该不是线程安全的。 还有 MessageChain 是基于 STL 实现的,STL 不是线程安全的,所以它也不是线程安全的。(凭印象的回答,我很久没看这个库的代码了)

我记得STL可以线程安全 然后那个http库确实不怎么行,建议换cpr(虽然不是headeronly但是可以加submodule)

misaka-20002 avatar Oct 28 '22 05:10 misaka-20002

我怀疑在MiraiBot里面有部分不是线程安全的(

几乎都不是线程安全的,MiraiBot 类的 API 主要取决于那个HTTP库,那个库应该不是线程安全的。 还有 MessageChain 是基于 STL 实现的,STL 不是线程安全的,所以它也不是线程安全的。(凭印象的回答,我很久没看这个库的代码了)

我记得STL可以线程安全 然后那个http库确实不怎么行,建议换cpr(虽然不是headeronly但是可以加submodule)

libcpr(指正

misaka-20002 avatar Oct 28 '22 05:10 misaka-20002

还有其实可以考虑直接用STL内置thread库() threadpool已经多久没更新了

misaka-20002 avatar Oct 28 '22 06:10 misaka-20002

还有其实可以考虑直接用STL内置thread库() threadpool已经多久没更新了

需要控制线程的数量,不能收到一条消息就发起一条线程。这个项目属于 I/O 密集型程序,最好用协程,只是 C++20 的协程用起来过于麻烦。

cyanray avatar Oct 28 '22 06:10 cyanray

我怀疑在MiraiBot里面有部分不是线程安全的(

几乎都不是线程安全的,MiraiBot 类的 API 主要取决于那个HTTP库,那个库应该不是线程安全的。 还有 MessageChain 是基于 STL 实现的,STL 不是线程安全的,所以它也不是线程安全的。(凭印象的回答,我很久没看这个库的代码了)

cpp-httplib是线程安全的,他会block conccurent requests,我之前提的 #133 就是关于这个的(

Numendacil avatar Oct 28 '22 06:10 Numendacil

mirai-cpp的线程安全问题我觉得主要来自于断开链接以及重建链接的过程中,在单次open到close/lost connection之间应该是完全安全的

Numendacil avatar Oct 28 '22 06:10 Numendacil

还有其实可以考虑直接用STL内置thread库() threadpool已经多久没更新了

threadpool用的就是STL的threads库啊)

Numendacil avatar Oct 28 '22 06:10 Numendacil

好吧是我没看()

misaka-20002 avatar Oct 28 '22 06:10 misaka-20002