Flutter 之 Socket (三十二)

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();
    }
  }
}


image.png

示例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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末病曾,一起剝皮案震驚了整個濱河市牍蜂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泰涂,老刑警劉巖鲫竞,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異逼蒙,居然都是意外死亡从绘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門是牢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來僵井,“玉大人,你說我怎么就攤上這事驳棱∨玻” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵社搅,是天一觀的道長驻债。 經(jīng)常有香客問我乳规,道長,這世上最難降的妖魔是什么合呐? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任暮的,我火速辦了婚禮,結(jié)果婚禮上合砂,老公的妹妹穿的比我還像新娘青扔。我一直安慰自己,他們只是感情好翩伪,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布微猖。 她就那樣靜靜地躺著,像睡著了一般缘屹。 火紅的嫁衣襯著肌膚如雪凛剥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天轻姿,我揣著相機與錄音犁珠,去河邊找鬼。 笑死互亮,一個胖子當(dāng)著我的面吹牛犁享,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豹休,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼炊昆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了威根?” 一聲冷哼從身側(cè)響起凤巨,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎洛搀,沒想到半個月后敢茁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡留美,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年彰檬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片独榴。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡僧叉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出棺榔,到底是詐尸還是另有隱情瓶堕,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布症歇,位于F島的核電站郎笆,受9級特大地震影響谭梗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宛蚓,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一激捏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凄吏,春花似錦远舅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至任连,卻和暖如春蚤吹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背随抠。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工裁着, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拱她。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓二驰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親秉沼。 傳聞我的和親對象是個殘疾皇子诸蚕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容