Http 協(xié)議和 WebSocket 協(xié)議都屬于應(yīng)用層協(xié)議,除了它們礼殊,應(yīng)用層協(xié)議還有很多如:SMTP驹吮、FTP 等针史,這些應(yīng)用層協(xié)議的實現(xiàn)都是通過 Socket API 來實現(xiàn)的。
其實碟狞,操作系統(tǒng)中提供的原生網(wǎng)絡(luò)請求 API 是標(biāo)準(zhǔn)的啄枕,在 C 語言的 Socket 庫中,它主要提供了端到端建立鏈接和發(fā)送數(shù)據(jù)的基礎(chǔ)API族沃,而高級編程語言中的Socket庫其實都是對操作系統(tǒng)的 Socket API 的一個封裝频祝。所以,如果我們需要自定義協(xié)議或者想直接來控制管理網(wǎng)絡(luò)鏈接脆淹、又或者我們覺得自帶的 HttpClient 不好用想重新實現(xiàn)一個常空,這時我們就需要使用Socket。
Flutter 在 dart:io 包中提供了Socket的相關(guān)API
1. Socket 使用
Socket and ServerSocket
客戶端和服務(wù)器使用套接字通過TCP協(xié)議進行通信盖溺。 在服務(wù)器端使用ServerSocket漓糙,在客戶端使用Socket。 服務(wù)器使用bind()方法創(chuàng)建一個監(jiān)聽套接字咐柜,然后監(jiān)聽套接字上的傳入連接兼蜈。 例如:
ServerSocket.bind('127.0.0.1', 8081)
.then((serverSocket) {
serverSocket.listen((socket) {
socket.transform(utf8.decoder).listen(print);
});
});
客戶端使用connect()方法連接Socket,該方法返回Future拙友。 使用write(),writeln()或writeAll()是通過套接字發(fā)送數(shù)據(jù)的最簡單方法歼郭。 例如:
Socket.connect('127.0.0.1', 8081).then((socket) {
socket.write('Hello, World!');
});
客戶端連接Socket
var socket = await Socket.connect("baidu.com", 80);
客戶端監(jiān)聽Socket
socket.listen()
//onData:收到socket消息處理的回調(diào)
//onError:scoket發(fā)生錯誤時回調(diào)
//onDone:流關(guān)閉或者消息事件發(fā)送完成后回調(diào)
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError});
客戶端發(fā)送數(shù)據(jù)發(fā)送
mSocket!.writeln("GET / HTTP/1.1");
mSocket!.writeln("Host:baidu.com");
mSocket!.writeln("Connection:close");
mSocket!.writeln();
// 發(fā)送
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<String> _socketRequest() async {
try {
// 1.建立連接
var socket = await Socket.connect("baidu.com", 80);
// 2.根據(jù)http協(xié)議遗契,發(fā)送請求頭
socket.writeln("GET / HTTP/1.1");
socket.writeln("Host:baidu.com");
socket.writeln("Connection:close");
socket.writeln();
// 發(fā)送
await socket.flush();
// 3.讀取返回內(nèi)容,按照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<MSSocketRouter2> createState() => _MSSocketRouter2State();
}
class _MSSocketRouter2State extends State<MSSocketRouter2> {
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消息處理的回調(diào)
//onError:scoket發(fā)生錯誤時回調(diào)
//onDone:流關(guān)閉或者消息事件發(fā)送完成后回調(diào)
socket.listen(_onReceivedMsg,
onError: _onError, onDone: _onDone, cancelOnError: false);
});
} catch (e) {
print("連接socket出現(xiàn)異常,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();
// 發(fā)送
await mSocket!.flush();
}
}
_onSuccess() {
print("Socket onSuccess callback");
}
_onReceivedMsg(event) {
// 將Uint8List 轉(zhuǎn) 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
http://www.reibang.com/p/86e1d1b54be5