550 lines
14 KiB
HTML
550 lines
14 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="Expires" content="0">
|
|
<meta http-equiv="Pragma" content="no-cache">
|
|
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0"/>
|
|
<title>友乐游戏平台服务器</title>
|
|
<style>
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
body {
|
|
background: #f0f2f5;
|
|
color: #1f2328;
|
|
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
|
font-size: 13px;
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
#app {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
padding: 8px;
|
|
gap: 6px;
|
|
}
|
|
/* ---- 顶部标题栏 ---- */
|
|
#header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
background: #ffffff;
|
|
border: 1px solid #d0d7de;
|
|
border-radius: 6px;
|
|
padding: 8px 14px;
|
|
flex-shrink: 0;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
|
}
|
|
#title {
|
|
font-size: 15px;
|
|
font-weight: bold;
|
|
color: #0969da;
|
|
letter-spacing: 1px;
|
|
}
|
|
#srv-status { font-size: 13px; }
|
|
.status-connected { color: #1a7f37; }
|
|
.status-disconnected { color: #cf222e; }
|
|
.status-connecting { color: #9a6700; }
|
|
/* ---- 工具栏 ---- */
|
|
#toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
background: #ffffff;
|
|
border: 1px solid #d0d7de;
|
|
border-radius: 6px;
|
|
padding: 5px 10px;
|
|
flex-shrink: 0;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
|
}
|
|
#toolbar button {
|
|
background: #f6f8fa;
|
|
color: #57606a;
|
|
border: 1px solid #d0d7de;
|
|
border-radius: 4px;
|
|
padding: 3px 10px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
font-family: inherit;
|
|
transition: background 0.15s, color 0.15s;
|
|
}
|
|
#toolbar button:hover { background: #e8eef4; color: #1f2328; }
|
|
#toolbar button.active { color: #1a7f37; border-color: #1a7f37; background: #dafbe1; }
|
|
#log-count {
|
|
margin-left: auto;
|
|
color: #8c959f;
|
|
font-size: 12px;
|
|
white-space: nowrap;
|
|
}
|
|
/* ---- 日志区域 ---- */
|
|
#log-container {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
background: #ffffff;
|
|
border: 1px solid #d0d7de;
|
|
border-radius: 6px;
|
|
padding: 6px 8px;
|
|
line-height: 1.65;
|
|
min-height: 0;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
|
}
|
|
#log-container::-webkit-scrollbar { width: 6px; }
|
|
#log-container::-webkit-scrollbar-track { background: #f6f8fa; }
|
|
#log-container::-webkit-scrollbar-thumb { background: #d0d7de; border-radius: 3px; }
|
|
.log-line {
|
|
padding: 1px 4px;
|
|
border-radius: 2px;
|
|
word-break: break-all;
|
|
white-space: pre-wrap;
|
|
}
|
|
.log-line:hover { background: rgba(0,0,0,0.04); }
|
|
/* 日志类型颜色 */
|
|
.log-info { color: #57606a; }
|
|
.log-system { color: #0969da; }
|
|
.log-success { color: #1a7f37; }
|
|
.log-warning { color: #9a6700; }
|
|
.log-error { color: #cf222e; }
|
|
.log-data { color: #8250df; }
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="app">
|
|
<div id="header">
|
|
<span id="title">● 友乐游戏平台服务器</span>
|
|
<span id="srv-status" class="status-disconnected">● 未连接</span>
|
|
</div>
|
|
<div id="toolbar">
|
|
<button onclick="clearLog()">清空日志</button>
|
|
<button id="btn-autoscroll" class="active" onclick="toggleAutoScroll()">自动滚动 ✓</button>
|
|
<span id="log-count">共 0 条</span>
|
|
</div>
|
|
<div id="log-container"></div>
|
|
</div>
|
|
|
|
<script type="text/javascript" src="md5.js"></script>
|
|
<script type="text/javascript" src="indexDb.js"></script>
|
|
<script type="text/javascript" src="lz-string.js"></script>
|
|
<script type="text/javascript" src="minhttp.js"></script>
|
|
<script type="text/javascript" src="packet.js"></script>
|
|
<script type="text/javascript">
|
|
// Websocket object
|
|
var ws = null;
|
|
// Websocket 连接地址
|
|
var ws_url = "ws://127.0.0.1:3088";
|
|
//临时屏蔽某个游戏的数据包
|
|
var blacknamelist_game = [];
|
|
// 日志控制
|
|
var _autoScroll = true;
|
|
var _logCount = 0;
|
|
var MAX_LOG_LINES = 500;
|
|
|
|
// Helper functions
|
|
function $() {
|
|
return document.getElementById(arguments[0]);
|
|
}
|
|
|
|
function _getLogClass(msg) {
|
|
var m = (msg || '').toLowerCase();
|
|
if (m.indexOf('error') > -1 || m.indexOf('报错') > -1 || m.indexOf('非法') > -1 || m.indexOf('出错') > -1) return 'log-error';
|
|
if (m.indexOf('close') > -1 || m.indexOf('断开') > -1 || m.indexOf('disconn') > -1) return 'log-warning';
|
|
if (m.indexOf('connected') > -1 || m.indexOf('连接') > -1 || m.indexOf('login') > -1) return 'log-success';
|
|
if (m.indexOf('tcp') > -1 || m.indexOf('http') > -1 || m.indexOf('ws:') > -1) return 'log-system';
|
|
return 'log-info';
|
|
}
|
|
|
|
function logMsg(msg) {
|
|
var container = $('log-container');
|
|
if (!container) return;
|
|
_logCount++;
|
|
// 超出上限时移除最早的一行
|
|
if (container.children.length >= MAX_LOG_LINES) {
|
|
container.removeChild(container.firstChild);
|
|
}
|
|
var line = document.createElement('div');
|
|
line.className = 'log-line ' + _getLogClass(msg);
|
|
line.textContent = msg;
|
|
container.appendChild(line);
|
|
$('log-count').textContent = '共 ' + _logCount + ' 条';
|
|
if (_autoScroll) {
|
|
container.scrollTop = container.scrollHeight;
|
|
}
|
|
}
|
|
|
|
function logmsg(msg) {
|
|
logMsg(msg);
|
|
}
|
|
|
|
function clearLog() {
|
|
var container = $('log-container');
|
|
container.innerHTML = '';
|
|
_logCount = 0;
|
|
$('log-count').textContent = '共 0 条';
|
|
}
|
|
|
|
function toggleAutoScroll() {
|
|
_autoScroll = !_autoScroll;
|
|
var btn = $('btn-autoscroll');
|
|
btn.textContent = _autoScroll ? '自动滚动 ✓' : '自动滚动 ✗';
|
|
btn.className = _autoScroll ? 'active' : '';
|
|
}
|
|
|
|
function setStatus(state) {
|
|
var el = $('srv-status');
|
|
if (state === 'connected') {
|
|
el.className = 'status-connected';
|
|
el.textContent = '● 已连接';
|
|
} else if (state === 'connecting') {
|
|
el.className = 'status-connecting';
|
|
el.textContent = '● 连接中…';
|
|
} else {
|
|
el.className = 'status-disconnected';
|
|
el.textContent = '● 未连接';
|
|
}
|
|
}
|
|
|
|
function sendMsg(msg) {
|
|
try{
|
|
ws.send(msg);
|
|
}catch(e){
|
|
console.log(min_now() + "发包报错。");
|
|
console.log(msg);
|
|
console.log(e);
|
|
}
|
|
}
|
|
function sendmsg(msg) {
|
|
try{
|
|
ws.send(msg);
|
|
}catch(e){
|
|
console.log(min_now() + "发包报错。");
|
|
console.log(msg);
|
|
console.log(e);
|
|
}
|
|
}
|
|
//重新连接
|
|
function reconnect(){
|
|
ws = null;
|
|
connectWebSocket();
|
|
}
|
|
// Websocket functions
|
|
function connectWebSocket() {
|
|
OnBeginConnectedServerChat();
|
|
if ("WebSocket" in window) {
|
|
// Create new websocket connection
|
|
setStatus('connecting');
|
|
ws = new WebSocket(ws_url);
|
|
|
|
// Called after connection is established
|
|
ws.onopen = function() {
|
|
setStatus('connected');
|
|
logMsg(min_now() + ' tcp connected to: ' + ws.url);
|
|
sendMsg('dfw19770109'); //告诉ServerChat.exe我是逻辑服务器
|
|
ws.wsisclose = false;
|
|
};
|
|
|
|
// Called when connection is closed
|
|
ws.onclose = function() {
|
|
ws.wsisclose = true;
|
|
setStatus('disconnected');
|
|
logMsg(min_now() + " Connection closed!");
|
|
ws.reconnecttimer = min_ontimeout(reconnect, 5000);
|
|
};
|
|
|
|
// Called when a new message is received
|
|
ws.sendall = function (msg) {
|
|
if (ws.wsisclose){
|
|
return;
|
|
}
|
|
if (typeof(msg) == 'string') {
|
|
sendMsg('@toallall:' + msg);
|
|
}
|
|
else
|
|
{
|
|
var s = JSON.stringify(msg);
|
|
sendMsg('@toallall:' + s);
|
|
}
|
|
}
|
|
|
|
//Send message to HTTP client
|
|
ws.sendtou = function (head, msg) {
|
|
if (ws.wsisclose){
|
|
return;
|
|
}
|
|
sendMsg(head + msg);
|
|
}
|
|
|
|
//Send message to TCP client
|
|
ws.sendbyids = function(ids, msg) {
|
|
if (ws.wsisclose){
|
|
return;
|
|
}
|
|
var s = '@tooneone:';
|
|
var str_ids;
|
|
if (typeof(msg) == 'string')
|
|
{}
|
|
else
|
|
{
|
|
msg = JSON.stringify(msg);
|
|
}
|
|
if (typeof(ids) == 'string')
|
|
{
|
|
str_ids = ids;
|
|
}
|
|
else
|
|
{
|
|
//ids:[1,5,8] 要转成字符串 1,5,8
|
|
str_ids = ids[0];
|
|
for (var i=1; i<ids.length; i++)
|
|
{
|
|
str_ids = str_ids + ',' + ids[i];
|
|
}
|
|
}
|
|
s = s + str_ids + ':' + msg;
|
|
sendMsg(s);
|
|
}
|
|
|
|
ws.sendclosetcp = function(ids) {
|
|
if (ws.wsisclose){
|
|
return;
|
|
}
|
|
var s = '@toclosed:';
|
|
var str_ids;
|
|
if (typeof(ids) == 'string') {
|
|
str_ids = ids;
|
|
}else{
|
|
//ids:[1,5,8] 要转成字符串 1,5,8
|
|
str_ids = ids[0];
|
|
for (var i=1; i<ids.length; i++)
|
|
{
|
|
str_ids = str_ids + ',' + ids[i];
|
|
}
|
|
}
|
|
s = s + str_ids+ ':a';
|
|
sendMsg(s);
|
|
}
|
|
|
|
ws.onmessage = function (msg) {
|
|
if (msg.data)
|
|
{
|
|
// logMsg(msg.data);
|
|
var arr = msg.data;
|
|
var tou = arr.substr(10, 5);
|
|
// var arrs = arr.split(":");
|
|
//取前面50个字符,以免全字符split,提高效率
|
|
var arr50 = arr.substr(0, 50);
|
|
var arrs = arr50.split(":");
|
|
|
|
if (tou == 'http_')
|
|
{//http
|
|
var s1 = '@tooneone' + ':' + arrs[1] + ':';
|
|
var s2 = "";
|
|
if (arrs.length > 2)
|
|
{//是数据,否则是命令
|
|
s2 = msg.data.substr(s1.length, msg.data.length-s1.length);
|
|
}
|
|
OnHttpMessage(s1, s2);
|
|
}
|
|
else
|
|
{//tcp
|
|
var ss0 = arrs[0];
|
|
var ss1 = arrs[1];
|
|
var sip = arrs[2];
|
|
var s01 = ss0 + ':' + ss1 + ':' + sip + ':';
|
|
var ss2 = "";
|
|
if (arrs.length > 3)
|
|
{//是数据,否则是命令
|
|
ss2 = msg.data.substr(s01.length, msg.data.length - s01.length);
|
|
}
|
|
OnTcpMessage(ss0, ss1, sip, ss2);
|
|
|
|
// var ss0 = arrs[0];
|
|
// var ss1 = arrs[1];
|
|
// var s01 = ss0 + ':' + ss1 + ':';
|
|
// var ss2 = "";
|
|
// if (arrs.length > 2)
|
|
// {//是数据,否则是命令
|
|
// ss2 = msg.data.substr(s01.length, msg.data.length - s01.length);
|
|
// }
|
|
// OnTcpMessage(ss0, ss1, "", ss2);
|
|
}
|
|
};
|
|
|
|
return;
|
|
};
|
|
}
|
|
else
|
|
{
|
|
logMsg('Browser doesn\'t support websockets!');
|
|
}
|
|
|
|
OnAfterConnectedServerChat();
|
|
}
|
|
|
|
//server.html连接ServerChat.exe前的事件
|
|
function OnBeginConnectedServerChat()
|
|
{
|
|
}
|
|
|
|
//server.html连接ServerChat.exe后的事件
|
|
function OnAfterConnectedServerChat()
|
|
{
|
|
//给packet_face传递发包函数
|
|
if (typeof(packet_face) != "undefined")
|
|
{
|
|
global.packet_face.SendPack_Tcp = ws.sendbyids;
|
|
global.packet_face.SendPack_Http = ws.sendtou;
|
|
}
|
|
}
|
|
|
|
//收到客户端http发包触发的事件
|
|
function OnHttpMessage(str_httpid, str_data)
|
|
{
|
|
try
|
|
{
|
|
str_data = min_replaceAll(str_data, "%", "");
|
|
str_data = decodeURIComponent(str_data); //解码
|
|
}
|
|
catch(e)
|
|
{
|
|
console.log("OnHttpMessage_decodeURIComponent:" + str_data);
|
|
return;
|
|
}
|
|
|
|
var s = "";
|
|
s = str_data.substr(0, 6);
|
|
if (s == "&data=") {
|
|
str_data = str_data.replace("&data=", "");
|
|
}
|
|
s = str_data.substr(0, 5);
|
|
if (s == "data=") {
|
|
str_data = str_data.replace("data=", "");
|
|
}
|
|
s = str_data.substr(0, 2);
|
|
if (s == "&=") {
|
|
str_data = str_data.replace("&=", "");
|
|
}
|
|
s = str_data.substr(0, 1);
|
|
if (s == "&") {
|
|
str_data = str_data.replace("&", "");
|
|
}
|
|
|
|
if (typeof(packet_face) != "undefined") {
|
|
if (str_data) {
|
|
try
|
|
{
|
|
var json_data = JSON.parse(str_data);
|
|
if (json_data){
|
|
json_data.conmode = "http";
|
|
json_data.fromid = str_httpid;
|
|
packet_face.ReceivePack(json_data);
|
|
}
|
|
}
|
|
catch(e)
|
|
{
|
|
console.log(min_now() + " str_data:" + str_data);
|
|
console.log(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//收到客户端tcp发包触发的事件
|
|
function OnTcpMessage(str_com, str_tcpid, str_ip, str_data)
|
|
{
|
|
switch (str_com)
|
|
{
|
|
case "@toconcon": //连上ServerChat.exe
|
|
break;
|
|
|
|
case "@tologin1": //客户端连接上
|
|
if (typeof(packet_face) != "undefined")
|
|
{
|
|
packet_face.OnTcpConnected(str_tcpid);
|
|
}
|
|
break;
|
|
|
|
case "@toleave1": //客户端断开
|
|
if (typeof(packet_face) != "undefined")
|
|
{
|
|
packet_face.OnTcpDisConnected(str_tcpid);
|
|
}
|
|
break;
|
|
|
|
case "@toserver": //客户端发包
|
|
if (typeof(packet_face) != "undefined")
|
|
{
|
|
try
|
|
{
|
|
//去除%,否则decodeURIComponent(str_data)会报错
|
|
str_data = min_replaceAll(str_data, "%", "");
|
|
//解码
|
|
str_data = decodeURIComponent(str_data);
|
|
var json_data = JSON.parse(str_data);
|
|
}
|
|
catch(e)
|
|
{
|
|
console.log(min_now() + "非法的TCP连接");
|
|
var errlog = {};
|
|
errlog.com = str_com;
|
|
errlog.tcpid = str_tcpid;
|
|
errlog.ip = str_ip;
|
|
errlog.data = str_data;
|
|
console.log(errlog);
|
|
//断开tcp连接
|
|
ws.sendclosetcp(str_tcpid);
|
|
return;
|
|
}
|
|
|
|
if (json_data){
|
|
try
|
|
{
|
|
//屏蔽某个有错的route
|
|
if (json_data.route){
|
|
if (min_ary_indexof(blacknamelist_game, json_data.route) > -1){
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
catch(e)
|
|
{}
|
|
|
|
json_data.conmode = "tcp";
|
|
json_data.fromid = str_tcpid;
|
|
json_data.ip = str_ip;
|
|
|
|
try
|
|
{
|
|
packet_face.ReceivePack(json_data);
|
|
}
|
|
catch(e)
|
|
{
|
|
console.log(min_now() + "执行rpc出错");
|
|
console.log(json_data);
|
|
console.log(e);
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
console.log(min_now() + "非法的TCP连接");
|
|
var errlog = {};
|
|
errlog.com = str_com;
|
|
errlog.tcpid = str_tcpid;
|
|
errlog.ip = str_ip;
|
|
errlog.data = str_data;
|
|
console.log(errlog);
|
|
//断开tcp连接
|
|
ws.sendclosetcp(str_tcpid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
window.onload = connectWebSocket();
|
|
</script>
|
|
</body>
|
|
</html>
|