前言
本文将介绍基于dart:io的Socket,进行TCP基本编程,实现服务端与客户端的监听、连接、数据收发。
示例代码:https://gitee.com/tilongzs/flutter_study_demo/tree/master/socket_tcp_test
使用插件:
- wifi_ip: ^0.0.1
- buffer: ^1.0.7
服务端Socket
bind
通过ServerSocket.bind()来创建一个ServerSocket,参数指定为要bind的IP、端口。
_serverSocket = await ServerSocket.bind(InternetAddress.tryParse(serverIP), serverPot);
listen
通过_serverSocket.listen()来绑定Accept、Error、Close事件处理函数。
_serverSocket.listen(onAccept, onError: onSocketError, onDone: onServerListenSocketClose);
onAccept()处理来自客户端的连接,将与该客户端通信的Socket保存起来。注意,示例代码只保存最新的一个,实际编程时应该保存在某个列表里。
void onAccept(Socket socket) {
_connectedSocket = socket;
_connectedSocket.listen(onSocketRecv, onError: onSocketError, onDone: onSocketClose);
printLog('有新客户端连接:${_connectedSocket.remoteAddress.address}:${_connectedSocket.remotePort}');
}
onSocketError()处理错误消息。
void onSocketError(Object error) {
printLog('与服务端已连接的socket出现错误,error=${error.toString()}');
}
onServerListenSocketClose()处理停止监听消息,将ServerSocket变量设置为null。
void onServerListenSocketClose() {
_serverSocket = null;
printLog('服务端停止监听');
}
已连接的客户端
_connectedSocket.listen(onSocketRecv, onError: onSocketError, onDone: onSocketClose);
已连接的客户端需要绑定Recv、Error、Close事件处理函数。
onSocketRecv()处理接收到的数据。这里假定客户端发来的是UTF8数据。
void onSocketRecv(Uint8List data) {
var decoder = Utf8Decoder();
String msg = decoder.convert(data); // 将UTF8数据解码
printLog('收到:${data.length}字节数据 内容:$msg');
}
onSocketError()处理错误消息。
void onSocketError(Object error) {
printLog('与服务端已连接的socket出现错误,error=${error.toString()}');
}
onSocketClose()处理客户端断开连接消息。注意,示例代码只保存最新的一个_connectedSocket ,实际编程时应该将其从某个列表里移除。
void onSocketClose() {
_connectedSocket = null;
printLog('断开连接');
}
发送数据
使用_connectedSocket.add(List<int> data)发送,这个函数不阻塞线程,但data发送之后不能修改。
onBtnSendMsg()示例发送UTF8数据。
void onBtnSendMsg() async {
if (_sendMsgController.text.isNotEmpty) {
if (_connectedSocket != null) {
var encoder = Utf8Encoder(); // 创建UTF8转换器,以支持发送中文
_connectedSocket.add(encoder.convert(_sendMsgController.text)); // 发送
}
_sendMsgController.text = '';
setState(() {});
}
}
onBtnSendBigBuffer()示例发送指定大小缓冲区的数据。
缓冲区可以使用Dart的ByteData,也可以使用推荐的插件buffer。
void onBtnSendBigBuffer(){
/* var dataWriter = ByteDataWriter();
dataWriter.writeUint8(1); // 1个字节
_connectedSocket.add(dataWriter.toBytes());*/
var byteData = ByteData(1024*1024);
_connectedSocket.add(byteData.buffer.asUint8List());
}
断开连接
断开已连接的客户端:
_connectedSocket.close(); _connectedSocket = null;
停止监听:
_serverSocket.close(); _serverSocket = null;
客户端Socket
connect
通过Socket.connect()创建一个连接服务端的socket,实现客户端与服务端的监听、连接、数据收发。
_connectedSocket = await Socket.connect(serverIP, serverPot,
timeout: Duration(milliseconds: 500));
通过_connectedSocket.listen()来绑定Recv、Error、Close事件处理函数,与服务端相同。
_connectedSocket.listen(onSocketRecv, onError: onSocketError, onDone: onSocketClose);
断开连接
_connectedSocket.close(); _connectedSocket = null;
