![1f7edc4188c924e5cce4156ced554182.png](https://i-blog.csdnimg.cn/blog_migrate/cc7150a98eae18995926e3388a4ea0b2.jpeg)
http:// socket.io 是一个使用websocket进行socket链接的协议包,定义了聊天相关的协议和使用websocket的规范,基于该协议可以很好的构建一个聊天系统,而不需要自己构建聊天室协议,如房间,消息发送指定人等
flutter中可以使用socket_io_client作为http://socket.io的客户端接入方式,socket_io_client是参考http://socket.io的js包来实现的,其中的api和js包的类似,可以方便的接入由http://socket.io接入的服务端应用,包括node,java等实现
- 引入socket_io_client包
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
# socket.io包
socket_io_client: ^0.9.9
2. 调用http://socket.io中的api链接socket服务端
IO.Socket channel;
@override
void initState() {
super.initState();
_listenWebSocket();
}
void _listenWebSocket() async {
// 构建请求头,可以放一些cookie等信息,这里加上了origin,因为服务端有origin校验
Map<String, dynamic> headers = new Map();
headers['origin'] = 'http://127.0.0.1:7001';
// 建立websocket链接
// 链接的书写规范,schame://host:port/namespace, 这里socket_io_client在处理链接时候会把path和后面的query参数都作为namespace来处理,所以如果我们的namespace是/的话,就直接使用http://host/
channel = IO.io('http://127.0.0.1:7001/', <String, dynamic>{
// 请求的path
'path': '/ws',
// 构造的header放这里
'extraHeaders': headers,
// 查询参数,扔这里
'query': {
'EIO': 3,
'transport': 'websocket'
},
// 说明需要升级成websocket链接
'transports': ['websocket'],
});
// 链接建立成功之后,可以发送数据到socket.io的后端了
channel.on('connect', (_) {
print('connect');
// 发送消息和回调函数给socket.io服务端,在服务端可以直接获取到该方法,然后调用
channel.emitWithAck('exchange', '11111', ack: (data) {
print('ack $data') ;
if (data != null) {
print('from server $data');
} else {
print("Null") ;
}
});
});
// 链接建立失败时调用
channel.on('error', (data){
print('error');
print(data);
});
// 链接出错时调用
channel.on("connect_error", (data) => print('connect_error: '));
// 链接断开时调用
channel.on('disconnect', (_) => print('disconnect======'));
// 链接关闭时调用
channel.on('close', (_) => print('close===='));
// 服务端emit一个message的事件时,可以直接监听到
channel.on('message', (data) {
print('onmessage');
print(data);
});
}
// 关闭websocket链接,避免内存占用
@override
void dispose() {
super.dispose();
print('close');
channel.close();
}
在使用socket_io_client时,主要需要注意的地方是使用io()创建链接时,链接的构建和一些header头,path等参数的编写,如果链接出错,一般会直接close掉链接
如果是namespace写错的话,会提示:
invalid namespace
这些都可以通过检查链接和path是否写对来校验是否能正常建立链接
使用ack的方式,可以直接在当前的发送消息的函数中,相应数据,而不需要服务端通过事件来发送数据回来,这样能保证数据的一致性