Http 协议和 WebSocket 协议都属于应用层协议,除了它们,应用层协议还有很多如:SMTP、FTP 等,这些应用层协议的实现都是通过 Socket API 来实现的。
其实,操作系统中提供的原生网络请求 API 是标准的,在 C 语言的 Socket 库中,它主要提供了端到端建立链接和发送数据的基础API,而高级编程语言中的Socket库其实都是对操作系统的 Socket API 的一个封装。所以,如果我们需要自定义协议或者想直接来控制管理网络链接、又或者我们觉得自带的 HttpClient 不好用想重新实现一个,这时我们就需要使用Socket。
Flutter 在 dart:io 包中提供了Socket的相关API
1. Socket 使用
Socket and ServerSocket
客户端和服务器使用套接字通过TCP协议进行通信。 在服务器端使用ServerSocket,在客户端使用Socket。 服务器使用bind()方法创建一个监听套接字,然后监听套接字上的传入连接。 例如:
ServerSocket.bind('127.0.0.1', 8081)
.then((serverSocket) {
serverSocket.listen((socket) {
socket.transform(utf8.decoder).listen(print);
});
});
客户端使用connect()方法连接Socket,该方法返回Future。 使用write(),writeln()或writeAll()是通过套接字发送数据的最简单方法。 例如:
Socket.connect('127.0.0.1', 8081).then((socket) {
socket.write('Hello, World!');
});
客户端连接Socket
var socket = await Socket.connect("baidu.com", 80);
客户端监听Socket
socket.listen()
//onData:收到socket消息处理的回调
//onError:scoket发生错误时回调
//onDone:流关闭或者消息事件发送完成后回调
StreamSubscription listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError});
客户端发送数据发送
mSocket!.writeln("GET / HTTP/1.1");
mSocket!.writeln("Host:baidu.com");
mSocket!.writeln("Connection:close");
mSocket!.writeln();
// 发送
await mSocket!.flush();
socket.write('Hello, World!');
2.示例
示例1
import 'dart:convert';
import 'package:flutter/material.dart';
import 'dart:io';
class MSSocketRouter extends StatelessWidget {
const MSSocketRouter({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _socketRequest(),
builder: (context, snapshot) {
return Text(snapshot.data.toString());
},
),
);
}
Future _socketRequest() async {
try {
// 1.建立连接
var socket = await Socket.connect("baidu.com", 80);
// 2.根据http协议,发送请求头
socket.writeln("GET / HTTP/1.1");
socket.writeln("Host:baidu.com");
socket.writeln("Connection:close");
socket.writeln();
// 发送
await socket.flush();
// 3.读取返回内容,按照utf8解码为字符串
String _response = await utf8.decoder.bind(socket).join();
return _response;
} catch (e) {
return e.toString();
}
}
}
示例2
class MSSocketRouter2 extends StatefulWidget {
const MSSocketRouter2({Key? key}) : super(key: key);
@override
State createState() => _MSSocketRouter2State();
}
class _MSSocketRouter2State extends State {
late MSSocketManager _manager;
@override
void initState() {
super.initState();
_manager = MSSocketManager(host: "baidu.com", port: 80);
_manager.connectSocket();
Timer(Duration(seconds: 6), () {
print(_manager.mSocket);
_manager.writeMsg();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
);
}
}
class MSSocketManager {
MSSocketManager({required this.host, required this.port});
String host;
int port;
Socket? mSocket;
void connectSocket() async {
try {
Socket.connect(host, port, timeout: Duration(seconds: 5)).then((socket) {
mSocket = socket;
print('---------连接成功------------$mSocket');
_onSuccess();
//onData:收到socket消息处理的回调
//onError:scoket发生错误时回调
//onDone:流关闭或者消息事件发送完成后回调
socket.listen(_onReceivedMsg,
onError: _onError, onDone: _onDone, cancelOnError: false);
});
} catch (e) {
print("连接socket出现异常,e=${e.toString()}");
}
}
void writeMsg() async {
if (mSocket != null) {
mSocket!.writeln("GET / HTTP/1.1");
mSocket!.writeln("Host:baidu.com");
mSocket!.writeln("Connection:close");
mSocket!.writeln();
// 发送
await mSocket!.flush();
}
}
_onSuccess() {
print("Socket onSuccess callback");
}
_onReceivedMsg(event) {
// 将Uint8List 转 String fromCharCodes 或者 utf8.decode
// String s = String.fromCharCodes(event);
String a = utf8.decode(event);
print("Socket _onReceivedMsg $a");
print("Socket _onReceivedMsg callback $event ${event.runtimeType}");
}
_onError(e) {
print("Socket _onError callback $e");
}
_onDone() {
print("Socket _onDone callback");
}
}
https://book.flutterchina.club/chapter11/socket.html
https://www.jianshu.com/p/86e1d1b54be5