82.1 Introduction to Sockets
The Socket API is a set of basic, standardized APIs provided by the operating system to implement application-layer network protocols. It encapsulates transport-layer network protocols, mainly TCP/UDP. The Socket API provides fundamental APIs for establishing end-to-end connections and sending/receiving data. In high-level programming languages, the Socket API is essentially a wrapper around the operating system's Socket API.
The HTTP and WebSocket protocols we previously discussed are both application-layer protocols. Besides these, there are many other application-layer protocols, such as SMTP and FTP, all of which are implemented using the Socket API.
Therefore, if we need to create a custom protocol, directly manage network connections, or feel that the built-in HttpClient is inadequate and want to reimplement it, we need to use Sockets. Flutter's Socket API is located in the dart:io
package. Below, we will look at an example of using a Socket to implement a simple HTTP request.
82.2 Using Sockets to Implement an HTTP GET Request
Taking a request to Baidu's homepage as an example:
class SocketRoute extends StatelessWidget { const SocketRoute({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return FutureBuilder( future: _request(), builder: (context, snapShot) { return Text(snapShot.data.toString()); }, ); } _request() async { // Establish connection var socket = await Socket.connect("baidu.com", 80); // Initiate GET request header according to HTTP protocol socket.writeln("GET / HTTP/1.1"); socket.writeln("Host:baidu.com"); socket.writeln("Connection:close"); socket.writeln(); await socket.flush(); // Send // Read returned content and decode it as a UTF-8 string String _response = await utf8.decoder.bind(socket).join(); await socket.close(); return _response; } }
As we can see, using a Socket requires us to implement the HTTP protocol ourselves (we need to manage the communication process with the server). This example is a simple demonstration and does not handle redirection, cookies, etc. For the complete code, refer to the demo. Running it will yield results as shown in Figure :
The response content can be divided into two parts: the first part is the response header, and the second part is the response body. The server dynamically outputs the response body based on the request information. Since the request header in this example is quite simple, the response body may differ from what is accessed in a browser. Readers can add some request headers (like User-Agent) to see how the output changes.