前言
本文将介绍基于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;