【发布时间】:2021-07-29 17:28:43
【问题描述】:
(*在下面的帖子中,所有的IP、端口和密码都被更改了。抱歉这篇帖子的格式,编辑似乎不喜欢换行。)
问题:如何将整数存储为带符号的 32 位小端序?
背景:我正在尝试使用 RCon 在 bash 中连接到我的世界服务器。到目前为止,服务器显示正在接收连接,但我无法正确格式化数据包。我可以使用 mcrcon 连接到服务器并在 wireshark 中查看数据包,但是当我尝试使用我的 bash 脚本时,数据包长度、requestid 和类型值看起来不对。
以下是我的一些资料来源、故障排除数据和我的代码,可能有助于回答问题。
实现:https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
服务器控制台:
[22:24:09 警告]:跟不上!服务器是否超载?运行 3190 毫秒或 63 个滴答声
[22:24:23 INFO]:Rcon 连接来自:/164.256.8.10
[22:24:34 WARN]:跟不上!服务器是否超载?运行 9961 毫秒或 199 个滴答声
[22:24:55 警告]:跟不上!服务器是否超载?运行 2006 毫秒或 40 个滴答声
[22:25:12 INFO]:Rcon 连接来自:/164.256.8.10
.
代码:
#!/bin/bash
# Length int Length of remainder of packet
# Request ID int Client-generated ID
# Type int 3 for login, 2 to run a command, 0 for a multi-packet response
# Payload byte[] ASCII text
# 2-byte pad byte, byte Two null bytes
# Connection details
RCON_HEADER=$(echo -e "\xff\xff\xff\xff")
HOST="192.168.0.173"
PORT=12345
LENGTH=0 # Length of packet
REQUESTID=$RANDOM
PASSWORD="$1"
RES=0
COM=2
AUTH=3
NULL="\0"
COMMAND=${@:2}
echo "command: $COMMAND"
## Packet Format as per docs
#Packet Size in Bytes
#Request ID any int
#Type as above
#Body null terminated ascii string
#Empty string null terminated
build_packet()
{
local TYPE="$1";
$([ "$TYPE" == "$AUTH" ]) && local BODY="$PASSWORD" || local BODY=$COMMAND;
local DATA="$REQUESTID$TYPE$BODY";
local LENGTH=${#DATA};
local PACKET="$LENGTH$DATA";
echo $PACKET;
}
send()
{
#local PACKET="$1"
echo "sending: $PACKET"
printf "$PACKET%s\0%s\0" >&5 &
}
read ()
{
LENGTH="$1"
RETURN=`dd bs=$1 count=1 <&5 2> /dev/null`
}
echo "trying to open socket"
# try to connect
if ! exec 5<> /dev/tcp/$HOST/$PORT; then
echo "`basename $0`: unable to connect to $HOST:$PORT"
exit 1
fi
echo "socket is open"
PACKET=$(build_packet $AUTH $PASSWORD);
echo "Command: $COMMAND"
echo "Packet: $PACKET"
send $PACKET
read 7
echo "RETURN: $RETURN"
PACKET=$(build_packet $COM $COMMAND);
echo "Command: $COMMAND"
echo "Packet: $PACKET"
send $PACKET
read 7
echo "RETURN: $RETURN"
.
参考代码:https://blog.chris007.de/using-bash-for-network-socket-operation/
【问题讨论】:
-
自以为是:我什至不会想到使用 Bash 通过套接字处理二进制数据。曾经。反而会想到 Python 或 Perl。
-
bash根本无法存储任意二进制数据,因为任何空字节都被视为字符串终止符。 -
服务器上的所有其他任务都是由 bash 脚本执行的,如果我要使用 java 或 php 来执行此操作,那么我就会遇到语言接口的问题。如果可以做到这一点,它可能还会帮助很多其他人。
-
dd是用 C 语言编写的,但您可以毫不犹豫地在示例中使用它。 Bash 旨在运行以任意语言编写的任意程序,但它并非设计为通用语言。如果您真的想选择困难的路线,您可以在将所有数据放入变量或参数之前对其进行十六进制编码,并在发送时对其进行解码。 -
这实际上不是一个坏主意,我正在考虑类似 sed 或管道的东西,但编码可能是更灵活的选择。