preface

Dart also supports long Socket links. Next, let’s study together.

Dart: IO provides two classes. The first is Socket, which you can use as a client to connect to the server. The second is ServerSocket, which we will use to create a server and connect to the client.

The Socket client

The source code is as follows:

abstract class Socket implements Stream<Uint8List>, IOSink {
  
  static Future<Socket> connect(host, int port,
      {sourceAddress, Duration? timeout}) {
    final IOOverrides? overrides = IOOverrides.current;
    if (overrides == null) {
      return Socket._connect(host, port,
          sourceAddress: sourceAddress, timeout: timeout);
    }
    return overrides.socketConnect(host, port,
        sourceAddress: sourceAddress, timeout: timeout);
  }

  static Future<ConnectionTask<Socket>> startConnect(host, int port,
      {sourceAddress}) {
    final IOOverrides? overrides = IOOverrides.current;
    if (overrides == null) {
      return Socket._startConnect(host, port, sourceAddress: sourceAddress);
    }
    return overrides.socketStartConnect(host, port,
        sourceAddress: sourceAddress);
  }

  external static Future<Socket> _connect(host, int port,
      {sourceAddress, Duration? timeout});

  external static Future<ConnectionTask<Socket>> _startConnect(host, int port,
      {sourceAddress});

  void destroy();

  bool setOption(SocketOption option, bool enabled);

  Uint8List getRawOption(RawSocketOption option);

  void setRawOption(RawSocketOption option);

  int get remotePort;

  InternetAddress get address;

  InternetAddress get remoteAddress;

  Future close();

  Future get done;
}
Copy the code

From the source:

The Socket class has a static method connect(host, int port). The first parameter host can be a domain name or a String of IP addresses, or it can be an InternetAddress object.

Connect returns a Future

object that is called back when the Socket is connected to the host.

// socket_pratice1.dart
void main() {
 Socket.connect("www.baidu.com", 80).then((socket) {
   print('Connected to: '
       '${socket.remoteAddress.address}:${socket.remotePort}');
   socket.destroy();
 });
}
Copy the code

In this case, we connect to www.baidu.com through port 80 (open for HTTP). Once connected to the server, print out the IP address and port of the connection, and finally close the connection with socket.destroy(). Dart Socket_pratice1. dart The following output is displayed:

➜  socket_study dart socket_pratice1.dart \
socket_pratice2.dart: Warning: Interpreting this as package URI, 'package:io_pratice/socket_study/socket_pratice2.dart'.\
Connected to: 220.181.38.149:80
Copy the code

With a simple function call, Dart does the IP lookup for www.baidu.com for us to establish a connection to TCP, and we just have to wait. After the connection is established, we can interact with the server and do two things.

Write (String data) and socket.listen (void onData(data)).

// socket_pratice2.dart void main() {String indexRequest = 'GET/HTTP/1.1\nConnection: close\n\n'; \ Socket. Connect ("www.baidu.com", 80). Then ((Socket) {\ print('Connected to: '\ '${socket.remoteAddress.address}:${socket.remotePort}'); \ socket.listen((data) {\ print(new String.fromCharCodes(data).trim())); \ }, onDone: () { print("Done"); socket.destroy(); }); // Send data socket.write(indexRequest); }); }Copy the code

ServerSocket server

The source code is as follows:

abstract class ServerSocket implements Stream<Socket> {
  static Future<ServerSocket> bind(address, int port,
      {int backlog = 0, bool v6Only = false, bool shared = false}) {
    final IOOverrides? overrides = IOOverrides.current;
    if (overrides == null) {
      return ServerSocket._bind(address, port,
          backlog: backlog, v6Only: v6Only, shared: shared);
    }
    return overrides.serverSocketBind(address, port,
        backlog: backlog, v6Only: v6Only, shared: shared);
  }

  external static Future<ServerSocket> _bind(address, int port,
      {int backlog = 0, bool v6Only = false, bool shared = false});

  int get port;

  InternetAddress get address;

  Future<ServerSocket> close();
}
Copy the code

It is easy to connect to the server using sockets, and we can also use the ServerSocket object to create a server that can handle client requests. First we need to bind to a specific port and listen, using the serversocket. bind(address, int port) method. This method returns the Future

object, which returns the ServerSocket object upon successful binding. After the serversocket. listen(void onData(Socket Event)) method registers the callback, the Socket object connected to the client can be obtained. Note that the port number needs to be greater than 1024 (reserved range).

// serversocket_pratice1.dart void main() { ServerSocket.bind(InternetAddress.anyIPv4, 4567) .then((ServerSocket server) { server.listen(handleClient); }); } void handleClient(Socket client) { print('Connection from ' '${client.remoteAddress.address}:${client.remotePort}'); client.write("Hello from simple server! \n"); client.close(); }Copy the code

Unlike the client, in Serversocket. listen we listen not for binary data, but for client connections. When a client initiates a connection, we get a Socket object that represents the client connection. Call the handleClient(Socket Client) function as an argument. Through this Socket object, we can obtain the client IP port and other information, and can communicate with it. After running this program, we need a client to connect to the server. You can change the conect address from the previous example to 127.0.0.0.1 and port to 4567, or you can use Telnet as the client initiating.

As you can see, Socket communication in Dart is easier to understand.

The resources

Flutter access to Aliyun public DNS Android/iOS SDK practice