Skip to content
This repository has been archived by the owner on Aug 16, 2024. It is now read-only.

Connect 失败 #116

Open
tiemoxishi opened this issue Sep 16, 2021 · 20 comments
Open

Connect 失败 #116

tiemoxishi opened this issue Sep 16, 2021 · 20 comments

Comments

@tiemoxishi
Copy link

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

@tiemoxishi
Copy link
Author

tiemoxishi commented Sep 16, 2021

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

adapters:
- http
- ws

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

@cyanray
Copy link
Owner

cyanray commented Sep 16, 2021

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

adapters:

  • http
  • ws

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

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

@tiemoxishi
Copy link
Author

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);

@cyanray
Copy link
Owner

cyanray commented Sep 16, 2021

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 写错了

@tiemoxishi
Copy link
Author

这是我的代码,如果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();
}

@cyanray
Copy link
Owner

cyanray commented Sep 16, 2021

getchar();

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

@tiemoxishi
Copy link
Author

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

@cyanray
Copy link
Owner

cyanray commented Sep 22, 2021

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

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

@tiemoxishi
Copy link
Author

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

@misaka-20002
Copy link
Contributor

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

@misaka-20002
Copy link
Contributor

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

@cyanray
Copy link
Owner

cyanray commented Oct 27, 2022

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

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

@misaka-20002
Copy link
Contributor

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

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

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

@misaka-20002
Copy link
Contributor

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

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

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

libcpr(指正

@misaka-20002
Copy link
Contributor

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

@cyanray
Copy link
Owner

cyanray commented Oct 28, 2022

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

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

@Numendacil
Copy link
Contributor

Numendacil commented Oct 28, 2022

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

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

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

@Numendacil
Copy link
Contributor

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

@Numendacil
Copy link
Contributor

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

threadpool用的就是STL的threads库啊)

@misaka-20002
Copy link
Contributor

好吧是我没看()

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants