Ruby [已解决] socket 编程求助。。。。

jjzxcc · 2013年04月22日 · 最后由 tumayun 回复于 2013年04月26日 · 5159 次阅读

我这边有个 server 以 socket 同步短联接方式提供类似生成支付密码的功能。 要求接收数据包结构为

名称           类型    长度
-----------------------------------
账号           字符    32
签发日期        字符    8
凭证种类        字符    1
签发金额        字符    16
凭证号码        字符    8
收方账号        字符    32

返回数据包结构为

名称           类型    长度
-----------------------------------
返回码         字符    6
支付密码       字符    16

这个 server 功能已经实现了 我这边作为 client 要怎么通过 socket 调用这个功能啊 纯小白一个,求助啊。

github 地址有吗?

@iBachue 没 github 地址,还要什么信息?

#2 楼 @jjzxcc 主要是想知道你 Server 接口部分是怎么写的

@iBachue server是另外一个人用C#写的,具体的也看不到,我这边只有一个类似功能简介的文档。

#4 楼 @jjzxcc 那这个文档拿出来看看?里面至少有一个C#版本的example吧

require 'socket'

s = TCPSocket.new 'localhost', 2000

while line = s.gets # Read lines from socket
  puts line         # and print them
end

s.close             # close socket when done

API 的例子啊。

@zgm api 的例子我都看了,还是不太会调这种实际的功能。主要是不知道 server 具体是怎么写的,文档基本都是上面这种只说了要接收和返回的数据包结构。 btw,这 api 例子返回为空。

@iBachue 真心没有啊,文档基本都是上面这种只说了要接收和返回的数据包结构。

#9 楼 @jjzxcc 哈 找那个人去 没有代码文档又不清晰的东西谁用啊

@fresh_fish 看过了,我想知道的是,比如我想访问这个功能,是用 socket 直接传按数据包结构拼凑的数据包给服务器,然后接收返回数据包吗?

#11 楼 @jjzxcc 是,socket 编程就是这样,你要按照给你的标准定义直接写字节出去,比如根据你那个文档就是往输出流里面写 32 个字节的帐号,再输出 8 个字节的签发日期,然后是一个字节的凭证种类,依次类推,直到写完;然后根据服务器端的返回依次读取,前 6 个字节是返回码,后 16 个字节是支付密码。

#12 楼 @donnior 为什么不能用 JSON 呢?

自定义传输格式的 API 最蛋疼了。先搞清楚,字符数不够是用什么填充,'\0' 还是 空格。按要求格式好字符串,比如是 '\0' 填充(|不需要,方便看清楚加的分隔符,...表示省略若干字符)。

|12341234...1234|20120124|5|234\0\0\0\0\0...\0\0|12345678|123123...1234|

依次是

|账号|日期|种类|金额|凭证|帐号|

格式化好后用 TCPSocket#write 发出去,然后用 TCPSocket#read 读 22 个字符。

raw_request = request.to_raw_request socket.write(raw_request) raw_response = socket.read(22) response = Response.parse_raw(raw_response)

可以先用 telnet 连上去试试 telnet hostname port 后依次输入 32 位帐号,8 位日期等所有输入然后看看服务器返回些什么东西。

PS,可以用 Array#packString#unpack 来格式化 request 和解析 response

["12341234", "20121230", "1", "200.3", "5555", "43214321"].pack("A32A8A1A16A8A32")

A32 表示 32 长度的字符串,不够长度在后面补齐空格。换成 a32 就是补齐'\0'。如果不是明文字符串,而是数字序列化也可以用相应的 flag 来格式化和解析。

#17 楼 @doitian 请问这个 pack 的格式是通用格式吗?还是只 ruby 的

不管什么语言,socket 编程都是差不多的。因为 socket 是操作系统实现的,语言的库只是封装一下。

#18 楼 @jjym 不通用,不过基本都会有个类似的库,比如 python 的 struct。只有数据格式商量好就能互相通信。不过最好是用现在的一些通信格式,比如 bson, protobuf, thrift

require 'socket'

s = TCPSocket.new '192.168.0.231', 8213
request = ["12341234", "20121230", "1", "200.30", "5555", "43214321"].pack("A32A8A1A16A8A32")
s.write(request)
response = s.read
puts response

s.close 

@doitian @donnior 我这样写行不?按上面的说明正常情况下,response 是不是该打印出返回数据包啊?为什么我 response 为空啊?

已解决,多谢各位帮助。

表示不懂。。

怎么解决的啊?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号