In the previous article, we have created a simple chat server based on ReactPHP Socket component. We have used a telnet client to connect to this server, now it’s time to create our own PHP client, also based on sockets. The source code for the server is available here on GitHub.
First of all, we need to create a streaming connection via React\Socket\Socket class. Its constructor requires an instance of the event loop:
This class provides only a single method connect($uri) to connect to the server, which is listening on the specified URI. Remember that our server is listening on 127.0.0.1:8080. This method returns a promise. When this promise is fulfilled you receive an instance of the streaming connection which implements React\Socket\ConnectionInterface. If the promise is rejected you get an exception:
ConnectionInterface itself extends React\Stream\DuplexStreamInterface that means that we can use this connection as a duplex stream (we can read and write data). For example, we can attach a handler to data event and then output everything we get from the server to the console:
To write data to the connection we can use write($data) method of the React\Stream\DuplexStreamInterface. But we need somehow to grab this data from the console and then write it to the connection. To read data from the console we can create an instance of the ReadableResourceStream:
And then attach a handler to the data event, so we can receive the input from the console and then write it to the connection:
We can also use a writable stream to output the data instead of echoing it. So, we create an instance of \React\Stream\WritableResourceStream class and pass it to the connection onFulfilled handler. Then every time we receive some data from the connection we can write() it to the stream:
Of course, you can argue that we are over-engineering here. Now, instead of the simple echo, we create an object, pass it to the closure and then call a method on it. Looks complex, but we can continue refactoring with streams. Now, when we have both readable and writable streams, and the connection itself also is a duplex stream, we can pipe them together:
Now the code looks much cleaner. Instead of listening to data events of the both connection and $stdin we simply create a chain of streams. When we receive the data from the console we write it to the connection. And at the same time when we receive the data from the connection, we output it on the console. And on this note, our chat client is done.
You can find a source code for this client on GitHub.