作为前端的我,平时接触到的都是 HTTP 服务, 最近公司的业务所致,需要 写一个 接口 与 游戏服务器 进行 socket TCP 通信,我是一脸蒙蔽,不过在同事的帮助下,
我还是 略懂了一点,所以记录一下

什么是TCP


TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议

socket


Node.js 原生提供了一个 net 包 ,可以用它来建立一个 socketTCP 通信,刚开始同事说 socket 我还以为是 web socket :( 真的惭愧,太菜了呀!

由于业务只需要搭建 客户端,所以代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const host = '192.168.xx.xx'
const port = 6666
const net = require('net')
const client = new net.Socket()
client.connect(port, host, () => {
client.write(Buffer)
debug('连接成功!')
})

client.on('data', (data) => {
res(data)
client.destroy()
})
client.on('error', (err) => {
rej(err)
debug('socket连接失败', err)
})

client.on('close', () => {
debug('连接关闭')
})

这样就轻松的与 游戏服务器进行了通信, 怎么发送数据给游戏服务器呢
使用 write 轻松搞定,因为不像 普通的 HTTP 一样 可以传个 JSON 之类的东东,这里必须写入一个 流 Buffer 过去

1
client.write(  Buffer  )

之前接触到 Buffer 很片面,做 头像图片上传的时候 接触到 了 一点点,但是这里更麻烦,需要自己拼一个 Buffer

Buffer


nodejs 创建buffer 之前的方式是

1
const buffer = new Buffer(len)

新版已经改成

1
Buffer.alloc(len)

效果是一样的,
由于 游戏服务器要求 拼一个 头部 + 消息内容,所以我这样来写,每个字节又有 32, 16 位 的

1
2
3
4
5
6
7
8
9
10
11
const createBuffer = (size) => (fnName) => (content, offset = 0) => {
const BYTE = "BE"
const _Buffer = Buffer.allocUnsafe(size).fill(0)
_Buffer[fnName](content, offset)
return _Buffer
}

const buf1= createBuffer(1)("writeInt8")(1)
const buf2 = createBuffer(4)("writeInt32BE")(0)

const HEADERS = Buffer.concat([buf1,buf2], buf1.length + buf2.length)

这样大概就拼出来了,使用 了 Buffer.concat 把多个buffer 组合起来,这里遇到了点阻碍,和知识盲点,就是 BELE,和 64位 的字节


后面查了下才知道 LELittle endian 小端序 BeBig Endian 大端序 , 这两者的区别就是排列顺序是相反的,自己还真是无知…


64位 字节 的问题 ,nodejs 只提供了 writeInt32BEwriteInt16BE 的方法,分别对应写 3216 字节,但是 不支持 64 位 的 当时我就蒙蔽了,最后找了一个 node-int64 的库 才得以解决 , 开源大法好 :)

1
2
3
4
5
6
7
8
const Int64 = require('node-int64')
const create64Buffer = (size = 8) => (value) => {
const nullBuffer = Buffer.alloc(8)
const int64 = new Int64(value)
const buffer_64 = int64.toBuffer()
buffer_64.copy(nullBuffer, 0)
return nullBuffer
}

过程虽然曲折,做的时候 感觉 很麻烦,不过在同事的帮助下,也是顺利的完成了这个任务,也让我对 Buffersocket 有了更深的认识,还是不错的!