最近在做一个小项目,需要在 python 和 Java 之间进行数据传输,用 socket 通信。 python 代码是这样的:
Head_Info = json.dumps(File_Dire)
Head_Info_Len = struct.pack('i', len(Head_Info))
#send file
Target_Sever.send(Head_Info_Len)
Target_Sever.send(Head_Info.encode('utf-8'))
with open(File, 'rb') as F:
data = F.read()
Target_Sever.sendall(data)
print ("done")
大概就是把数据的长度(4 字节)+数据的一些信息(json)+数据打成一个包。 差不多是这样的:
B {"Type": "File", "File_Name": "tempfile.fasttext", "File_Size": 6}hello!
在 python 里面是这样接收数据的:
Head_Struct = client.recv(1024)
Head_Len = struct.unpack('i',Head_Struct)[0]
File_Data_Raw = client.recv(Head_Len)# receve info
但到了 Java,输入变成了 IO 流,我并不能像 python 里面一样分批次拿信息了,只能一下拿完,但是对于文件传输,这相当于破坏了文件的结构,求一个解决思路(尽量在不改动 python 结构的前提下)。
indexOf
函数的一个问题我想把上述的数据包中的数据信息提取出来,代码如下
String ending = "}";
int info = Fileline.indexOf(ending) - 4;//减去 4 字节的报头
System.out.println(Fileline.substring(4, info));
输出的结果却是这样的
{"Type": "File", "File_Name": "tempfile.fasttext", "File_Size
请问是我在哪里出错了吗?
由于我只是对 coding 感兴趣,并没有进行系统学习,若出错,烦请指正 :)
Thanks again
1
dallaslu 2020-05-08 08:56:12 +08:00
和 indexOf 关系不大。重点在于 substring 第二个参数是 endIndex, 不是 length 。
另外 Java 接收数据是怎么写的呢? |
2
sandrew1945 2020-05-08 09:00:28 +08:00 1
Java 也可以按照长度分批读取流,建议用 netty 来写
|
3
luozic 2020-05-08 09:11:34 +08:00 1
使用一种公共的流定义,python 和 java 使用公共的定义通信,保证传输完整性的部分在流定义里面完成。
|
4
n770011 2020-05-08 09:13:57 +08:00
InputStream 函数 read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。可以分批次读。至于怎么解析,就看你数据协议怎么设计,如果不好解析那就证明你数据协议设计有问题。
|
5
HivenYang 2020-05-08 09:23:33 +08:00
拿到字节流,然后先读 4 个字节的长度,根据长度读取相应的字节数,然后进行解析,循环进行此操作,直到数据读完了,简单的么就直接用 io 包下的 ServerSocket,考虑性能么就研究下 NIO 、AIO 和 Netty
|
6
WhenAtRains 2020-05-08 09:23:54 +08:00
python 编码后,java 没有解码正确。我最近学习的 netty 里面 公共的比较简单的解码器有行编解器和固定长度编解码器。但是我觉得比较麻烦的是自己写一个编解码器,尤其是解码。
|
7
zhuangzhuang1988 2020-05-08 09:33:05 +08:00 via Android
最近刚刚在看 mercurial 的 command 传输协议,和你这个像
https://www.mercurial-scm.org/wiki/CommandServer 可以看下对应的 java 客服端怎么实现的 https://bitbucket.org/aragost/javahg/src/default/src/main/java/com/aragost/javahg/internals/HgInputStream.java |
8
yty2012g 2020-05-08 09:53:03 +08:00
使用 netty 可以很简单的处理吧,实现一个自定义的 ByteToMessageDecoder,首先标记一下读取位置,然后读取 4byte,得到消息长度,如果 ByteBuf 的剩余长度足够,就直接读取消息长度的内容,否则 return 并等待下一次读取,直到剩余长度满足消息长度。或者如果你不想一次读完,就每次读取就放到一个 byte 数组里面,直到 byte 数组满足待读取的长度。
|
10
aguesuka 2020-05-08 12:12:19 +08:00 via Android
java 里的 inputstream 的 read 方法返回的是这次读的 btye 数,比如传入长为 100 的数组,如果返回 40,那么只读到前 40 个,你需要循环 read,直到返回值为-1 或者读到了你想读的字节
|
11
aguesuka 2020-05-08 12:20:16 +08:00 via Android
比如 python 一次发了两条数据,一条长度为 8 一条为 16 。那第一次用长度为 4 的 byte[]读 4 个字节,第二次用长度为 8byte[]的读 8 个字节,便得到了第一条消息
|
12
xinQing 2020-05-13 18:06:01 +08:00
哈哈,解码错咯。建议用 netty 这样的网络库,自己用 Inputstream 拿自己做宝搞
|