At a somewhat lower level in the OSI model than HTTP clients and servers, we find sockets. They also enable interprocess communications across a network between clients and servers and are implemented on top of the TCP/IP. The classes that offer that functionality can be again found in dart:io
as follows:
The following steps will show you how to make a server socket work:
sockets
, socket_server.dart
):import 'dart:io'; import 'dart:convert'; InternetAddress HOST = InternetAddress.LOOPBACK_IP_V6; const PORT = 7654; void main() { ServerSocket.bind(HOST, PORT) .then((ServerSocket srv) { print('serversocket is ready'), srv.listen(handleClient); }) .catchError(print); ); } void handleClient(Socket client){ print('Connection from: ' '${client.remoteAddress.address}:${client.remotePort}'), // data from client: client.transform(UTF8.decoder).listen(print); // data to client: client.write("Hello from Simple Socket Server! "); client.close(); }
Start the server by running binsocket_server.dart
.
sockets
, socket_client.dart
):import 'dart:io'; InternetAddress HOST = InternetAddress.LOOPBACK_IP_V6; const PORT = 7654; void main() { Socket.connect("google.com", 80).then((socket) { print('Connected to: ' '${socket.remoteAddress.address}:${socket.remotePort}'), socket.destroy(); }); // prints: Connected to: 173.194.65.101:80 Socket.connect(HOST, PORT).then((socket) { print(socket.runtimeType); // data to server: socket.write('Hello, World from a client!'), // data from server: socket.listen(onData); }); } onData(List<int> data) { print(new String.fromCharCodes(data)); }
binsocket_client.dart
.The following is the output from the server console:
serversocket is ready
Connection from: ::200:0:8017:7b01%211558873:6564
Hello, World from a client!
The following is the output from a client console:
_Socket
Hello from Simple Socket Server!
Connected to: 74.125.136.139:80
We can see that there is two-way communication.
In step 1, a server to handle client socket connections is created by binding ServerSocket
to a specific TCP port that it will listen on. This bind
method returns a Future <ServerSocket>
. Again, we will use the Future.then
method to register our callback so that we know when the socket has been bound to the port. Then, the server starts listening and calls handleClient
for each incoming connection. This callback prints the remote address from the client, prints the data the client has sent, writes a message to the client, and then closes the connection.
In step 2, the client first opens a connection to www.google.com on port 80 (the port that serves web pages). After the socket is connected to the server, the IP address and port are printed to the screen. Then, the socket is shut down using socket.destroy
. In the second part of this step, we connect to the local socket server, write a message to it with socket.write
, and start listening to the server with socket.listen
. We transform the data that comes in as a list of integers into a string that is printed out.
Socket communication is often blocked by firewalls; if this is an issue, take a look at WebSockets in the following recipe.
Dart also supports UDP socket programming; the article by James Locum offers a detailed discussion at http://jamesslocum.com/post/77759061182.