写在前面
minecraft服务器的聊天消息和qq机器人互通这件事,之前也做过:基于socket的酷Q机器人与Minecraft消息同步功能的实现
但是啊,这个插件当时长时间使用之后,发现会卡服。。。。由此可见当时写的代码有多么垃圾。
另外一个原因就是现在更新到了sponge服务器,不是之前的bukkit/spigot服务端了,插件并不会兼容。所以我根据官网教程又重写简单地写了一下。
说实话,我并不会java,是完全不会的那种不会
实现了什么
sponge端,使用java编写了一个socket客户端,并在掉线时自动重连
c#端,直接用现成的库做了个soket服物端,启动插件后自动开启,并将相应传递给lua文件,给lua提供发送接口
java代码
这部分实现就基本按照官方文档+网上找的代码拼凑起来了。就像上面说的:我并不会java。我做的事情就是找几个需要的部分,能跑起来,最后拼到一起
socket客户端
客户端直接用了现成的代码,网上找的,稍微自己改了改把心跳那个判断去掉了:
class Client {
public Socket socket = null;
public OutputStream os = null;
public InputStream is = null;
/**
* 发送心跳包
*/
public void sendHeartbeat() {
try {
String heartbeat = "h";
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(120 * 1000);// 120s发送一次心跳
os.write(heartbeat.getBytes());
os.flush();
} catch (Exception e) {
//e.printStackTrace();
System.out.println("heartbeat send error");
try {
socket.close();
is.close();
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
public class SocketThread extends Thread {
@Override
public void run() {
sendHeartbeat();
while (true) {
try {
if (socket == null || socket.isClosed()) {
socket = new Socket("localhost", 23333); // 连接socket
os = socket.getOutputStream();
System.out.println("socket connected");
}
Thread.sleep(100);
is = socket.getInputStream();
int size = is.available();
if(size <= 0)
continue;
byte[] resp = new byte[size];
is.read(resp);
String response = new String(resp,"utf8");
try{
MessageChannel.TO_ALL.send(Text.of(response));
}
catch (Exception e){
}
//Logger.info("receive data:" + response);
} catch (Exception e) {
//e.printStackTrace();
System.out.println("socket error");
try {
socket.close();
is.close();
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
}
然后写一下开启服务器使用的函数,在插件的主类里写:
private Client tcpClient = null;
public void StartServer()
{
logger.info("starting tcp client");
tcpClient = new Client();
tcpClient.new SocketThread().start();
logger.info("tcp client started!");
}
public void SendTcp(String msg)
{
try{
tcpClient.os.write(msg.getBytes("utf8"));
tcpClient.os.flush();
}
catch (Exception e)
{
logger.info("tcp send failed!"+msg);
//e.printStackTrace();
System.out.println("heartbeat send error");
try {
tcpClient.socket.close();
tcpClient.is.close();
tcpClient.os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
sponge插件开启新线程貌似没什么限制,感觉上和之前写bukkit接口的插件有一些不同,之前都不敢开线程的
启动后直接调用开启这个线程就行了:
@Listener//服务器启动
public void onServerStart(GameStartedServerEvent event) {
StartServer();
logger.info("chat connector plugin start!");
}
c#服务端
c#服务端我直接用了SimpleTCP的库
namespace Native.Csharp.App.LuaEnv
{
class TcpServer
{
private static SimpleTcpServer server = new SimpleTcpServer();
public static void Start()
{
try
{
server.StringEncoder = Encoding.UTF8;
server.Start(23333);
Common.CqApi.AddLoger(Sdk.Cqp.Enum.LogerLevel.Info, "tcp server",
"tcp server started!");
server.DataReceived += (sender, msg) => {
//msg.Reply("Content-Type: text/plain\n\nHello from my web server!");
LuaEnv.RunLua(
$"message=[[{msg.MessageString.Replace("]", "] ")}]] ",
"envent/ReceiveTcp.lua");
};
}
catch(Exception e)
{
Common.CqApi.AddLoger(Sdk.Cqp.Enum.LogerLevel.Error, "tcp server",
"tcp server start failed!\r\n"+e.ToString());
}
}
public static void Send(string msg)
{
try
{
server.Broadcast(msg);
}
catch (Exception e)
{
Common.CqApi.AddLoger(Sdk.Cqp.Enum.LogerLevel.Error, "tcp server",
"tcp server send failed!\r\n" + e.ToString());
}
}
}
}
上面那段代码,在收到socket信息后,直接就推给lua脚本了,后面的信息处理就很随意了
效果
效果怎么说呢,也就那样吧,没什么功能
项目地址
sponge端:https://github.com/chenxuuu/chat-connecter
C#端:https://github.com/chenxuuu/receiver-meow
转载保留版权:晨旭的博客 » 《sponge通过socket与QQ群进行消息互通》如果喜欢可以: 点击右侧上方的邮件订阅,订阅本站