我有一个仅通过 telnet 进行通信的游戏服务器。 我有一个 Lucee 服务器在同一个服务器机房运行,并且想编写一个可以向游戏服务器发送命令的小型 Web 应用程序。 看起来很简单,但几十个小时后,我经历了很多空谷歌搜索和各种尝试的方法(如 tst10),但效果不佳。
我最终通过使用 Java 建立和管理 telnet 连接来实现这一点,并使用数据库表作为中间人,这样我的主线程就可以看到 telnet 连接所看到的内容。 我的工作代码如下。
此代码需要大量清理,但它是一个有效的概念证明,显示了如何完成它的基础知识。 希望其他有同样需求并且一直在用头撞墙的人会发现它很有用。
<cfcomponent>
<cffunction returntype="Struct" name="telnetConnect" access="public" output="no">
<cfargument name="SID" type="numeric" required="yes">
<cfargument name="telnetAdd" type="string" required="yes">
<cfargument name="telnetPort" type="numeric" required="yes">
<cfset retVal = structNew()>
<cfset retVal.success = true>
<cftry>
<cfparam name="application.telnet" default="#arrayNew()#">
<cfparam name="application.telnet[arguments.SID]" default="#structNew()#">
<cfparam name="application.telnet[arguments.SID].telnetClient" default="">
<cfparam name="application.telnet[arguments.SID].lastData" default="#Now()#">
<cfset application.telnet[arguments.SID].telnetData = "">
<cfset application.telnet[arguments.SID].isReading = false>
<cfscript>
// If there is an existing connection for this server; close it.
telnetClose(arguments.SID);
sleep(25);
// Load the Apache Commons Net TelnetClient class
application.telnet[arguments.SID].telnetClient = createObject("java", "org.apache.commons.net.telnet.TelnetClient").init();
// Connect to the Telnet server
application.telnet[arguments.SID].telnetClient.connect(arguments.telnetAdd, arguments.telnetPort);
// Get input and output streams
application.telnet[arguments.SID].inputStream = application.telnet[arguments.SID].telnetClient.getInputStream();
application.telnet[arguments.SID].outputStream = application.telnet[arguments.SID].telnetClient.getOutputStream();
</cfscript>
<cfcatch>
<cfset retVal.success = false>
<cfset retVal.cfcatch = cfcatch>
</cfcatch>
</cftry>
<cfreturn retVal />
</cffunction>
<cffunction returntype="Struct" name="telnetSend" access="public" output="no">
<cfargument name="SID" type="numeric" required="yes">
<cfargument name="message" type="string" required="yes">
<cfset retValSend = structNew()>
<cfset retValSend.success = true>
<cftry>
<cfscript>
command = "#arguments.message##chr(13)#";
application.telnet[arguments.SID].outputStream.write(command.getBytes());
application.telnet[arguments.SID].outputStream.flush();
</cfscript>
<cfcatch>
<cfset retValSend.success = false>
<cfset retValSend.cfcatch = cfcatch>
</cfcatch>
</cftry>
<cfreturn retValSend />
</cffunction>
<cffunction returntype="Struct" name="telnetRead" access="public" output="no">
<cfargument name="SID" type="string" required="yes">
<cfset var retVal = structNew()>
<cfset retVal.success = true>
<cftry>
<cfset application.telnet[arguments.SID].isReading = true>
<cfscript>
// Create an InputStreamReader from the InputStream
inputStreamReader = createObject("java", "java.io.InputStreamReader").init(application.telnet[arguments.SID].inputStream, "UTF-8");
// Create a char array for reading
charBuffer = createObject("java", "java.lang.reflect.Array").newInstance(createObject("java", "java.lang.Character").TYPE, 1024);
charsRead = 0;
totalRead = 0;
maxRead = 5120; // Max chars to read at a time
</cfscript>
<cfloop condition="totalRead lt maxRead">
<cfset charsRead = inputStreamReader.read(charBuffer, 0, 1024)>
<cfif charsRead is -1>
<cfbreak>
</cfif>
<cfset dataChunk = createObject("java", "java.lang.String").init(charBuffer, 0, charsRead)>
<cfset totalRead += charsRead>
<cfset application.telnet[arguments.SID].telnetData &= dataChunk>
<cfif dataChunk contains chr(13)>
<cfloop list="#dataChunk#" delimiters="#chr(13)#" index="thisLine">
<cfquery name="saveChunk">
insert into telnetMessages (mdate, message)
values (Now(),
<cfqueryparam cfsqltype="varchar" value="#thisLine#">)
</cfquery>
<cfset application.telnet[arguments.SID].lastData = Now()>
</cfloop>
<cfelse>
<cfquery name="saveChunk">
insert into telnetMessages (mdate, message)
values (Now(),
<cfqueryparam cfsqltype="varchar" value="#dataChunk#">)
</cfquery>
<cfset application.telnet[arguments.SID].lastData = Now()>
</cfif>
</cfloop>
<cfset application.telnet[arguments.SID].isReading = false>
<cfcatch>
<cfset application.telnet[arguments.SID].isReading = false>
<cfset retVal.success = false>
<cfset retVal.cfcatch = cfcatch>
</cfcatch>
<cffinally>
<cfset application.telnet[arguments.SID].isReading = false>
</cffinally>
</cftry>
<cfreturn retVal />
</cffunction>
<cffunction returntype="Struct" name="telnetClose" access="public" output="no">
<cfargument name="SID" type="numeric" required="yes">
<cfset retValClose = structNew()>
<cfset retValClose.success = true>
<cftry>
<cfscript>
if (application.telnet[arguments.SID].telnetClient.isConnected()) {
application.telnet[arguments.SID].telnetClient.disconnect();
}
</cfscript>
<cfcatch>
<cfset retValClose.success = false>
<cfset retValClose.cfcatch = cfcatch>
</cfcatch>
</cftry>
<cfreturn retValClose />
</cffunction>
</cfcomponent>