我在本地服务器上有一个特殊的应用程序(来自ucsim的8051模拟器),它只在一个端口上传输和期望不可打印的字符。基本上,我正在定义自己的数据格式。
如果我能看到每个字符的十六进制代码返回30列,并且能够键入十六进制字符代码,那么Telnet将是一个完美的程序。问题是,Linux附带的telnet只允许1行十六进制字符,并且可能在接收到某些字符时改变行为。
到目前为止,我最接近的解决方案是在wine中运行realterm程序并选择hex显示,但问题是如果我切换窗口它会锁定。直到我停止服务器发送和接收字符。所以我正在寻找一个原生的Linux解决方案。
至于接收数据,我可以轻松地使用此命令:
nc 127.0.0.1 port | od -tx1 -w30
但是当在数据流出的同一个开放端口上发送数据时,我尝试这个命令:
echo -e -n“\ x11 \ x22 \ x33”| nc 127.0.0.1端口
其中11,22,33是十六进制数字,发送回服务器。问题是当我尝试这个命令时,它只是停止,我必须按CTRL + C退出。
我的逻辑在这里是否正确?
或者是否有更好的命令我可以在unix中使用来查看发送二进制文件的服务器的十六进制字符,还可以传输在本地控制台输入的十六进制字符的二进制代码?
如果realterm程序目前在Linux中运行而不需要葡萄酒,那将是完美的。
附:我很抱歉,如果这个论坛不是这个问题的最佳位置,但就个人而言,我不介意制作一个包含50个命令的unix脚本,如果这就是我所取得的成就,因为我正在寻找的应用程序因为linux尚未存在。
nc
将从其标准输入读取并通过网络连接发送该数据。因此,如果您只是希望能够在终端中键入十六进制数字并将相应的二进制数发送到模拟器,则可以使用类似xxd -r -p
的数据将数据传输到nc
。即将nc 127.0.0.1 ...
改为xxd -r -p | nc 127.0.0.1 ...
。
然后,您可以在return
命令中键入“41 42 43 44”(后跟xxd
,因为交互式输入是行缓冲的),并且应该将“ABCD”输出到模拟器。 xxd
模式中的-r -p
将任何非十六进制数字视为分隔符,因此如果需要,可以在十六进制数字对之间放置空格以便于阅读。
如果您希望能够在开发会话期间从各种来源(交互式,从文件中捕获)发送不同类型的数据(十六进制,二进制),那么您可能需要安装第二个持久性nc
侦听器一个不同的端口来收集数据并将其提供给现有nc
的标准输入。
使用Python程序更新,该程序将从stdin读取十六进制并通过网络连接发送相应的二进制文件,并从连接读取数据并写入十六进制到标准输出。将它保存为类似nethex.py
的东西并将其调用为python nethex.py <host> <port>
。
#!/usr/bin/env python
import binascii
import re
import socket
import sys
import threading
def breakstring(string, maxchars):
return [ string[pos:(pos + maxchars)]
for pos in xrange(0, len(string), maxchars) ]
def to_hex(bytes):
lines = breakstring(binascii.hexlify(bytes), 32)
return ''.join([ (' '.join(breakstring(line, 2)) + '\n') for line in lines ])
def from_hex(s):
hexlist = re.sub('[^0-9A-Fa-f]', ' ', s).split()
pairs = [ '0' + hexstr if len(hexstr)%2 else hexstr for hexstr in hexlist ]
return binascii.unhexlify(''.join(pairs))
def connect(addr, port):
conn = None
infos = socket.getaddrinfo(addr, port, 0, socket.SOCK_STREAM)
for info in infos:
fam, typ, proto, fqdn, sa = info
try:
conn = socket.socket(fam, typ, proto)
except socket.error:
sys.stderr.write('socket: ' + str(se) + '\n')
continue
try:
conn.connect(sa)
except socket.error as se:
sys.stderr.write('connect: ' + str(se) + '\n')
conn.close()
conn = None
continue
break
return conn
class SockDrainer(threading.Thread):
def __init__(self, sock, sink):
super(SockDrainer, self).__init__()
self.sock = sock
self.sink = sink
def run(self):
drain(self.sock, self.sink)
def drain(sock, dest):
while True:
data = sock.recv(2048)
if not data:
break
outdata = to_hex(data)
dest.write(outdata)
dest.flush()
def fill(sock, source):
while True:
data = source.readline()
if not data:
break
try:
outdata = from_hex(data)
sock.send(outdata)
except socket.error:
break
try:
sock.shutdown(socket.SHUT_WR)
except socket.error:
pass
def nethex(addr, port):
conn = connect(addr, port)
if conn is not None:
drainer = SockDrainer(conn, sys.stdout)
drainer.daemon = True # thread will not block process termination
drainer.start()
fill(conn, sys.stdin)
drainer.join() # wait for rx'ed data to be handled
conn.close()
return conn is not None
if __name__ == '__main__':
result = nethex(sys.argv[1], sys.argv[2])
sys.exit(0 if result else 1)