上一篇文章是对socket编程的入门,此次咱们基于socket实现一个简单的收发消息的服务。php
实现思路:linux
先说服务端:编程
客户端:后端
因为PHP没有原生的从命令行接收用户输入的函数,因此这里经过如下方式来实现:socket
'/dev/stdin',这个是linux的标准输入,其实这个函数就是把linux的标准输入,重定向到咱们的后端PHP程序了。而后咱们的PHP程序就接收到了用户的输入,接着就能够把这个输入发送到回声服务程序的服务端了。函数
经过上面一篇文章,咱们已经对于建立套接字的流程有了必定的了解,在这里就很少说这些了。spa
接下来开始服务端的实现:命令行
echo_server.php:server
代码解读:图片
第1处:这里直接使用了上一篇文章介绍的stream_socket_server函数,能够一次性的完成socket的建立、绑定以及监听。
第2处:开始监听咱们建立的套接字(至于这里为何加上@,由于stream_socket_accept函数若是必定时间内没有收到客户端的链接的话,会报一个warning)
第3处:经过fread函数,读取输入缓冲区,一次读取1024个字节
第4处:将读取到的字符写入输入缓冲,从而发送到客户端。
经过上面的程序咱们已经实现了回声服务程序的服务端。
接下来咱们能够运行一下,会发现咱们的echo_server.php已经进入阻塞状态,等待客户端链接。
接着实现客户端:
echo_client.php
代码解读:
第1处:调用咱们的重定向标准输入函数,调用此函数以后,若是不输入任何字符,程序是不会执行到下一行的,由于这里会被阻塞。
第2处:若是咱们输入了q这个字符,将跳出while循环,紧接着会执行fclose,关闭链接。这里要注意一下,客户端关闭链接以后,会向服务端发送一个信号,告诉服务端我已经断开链接了,服务端接受到以后将关闭此客户端的链接。
第3处:将读取到的输入信息写入缓冲区,从而发送到服务端。
第4处到第5处是要重点讲解的内容。
此处为何不直接经过fread函数一次性读取服务端返回的消息呢?
如下是对于这个问题的解答:
对于每个socket,都有一个发送缓冲区和接收缓冲区。若是咱们发送的数据足够大,则可能分为两次发送。也就是说fwrite以后,咱们发送的字符有可能被分红两部分发送了,而服务端的代码是在不断的接收数据,而后返回数据。
因此客户端可能出现以下状况:发送一次字符以后,客户端还没有接收到所有的数据就调用了fread函数,从而打印屡次。
因此对于这个问题最好的解决方法就是,咱们客户端是可以提早知道要接收的字符大小的,因此这里经过strlen函数获取要接收的数据大小,若是不足这个大小则继续读取,直到知足条件以后再输出。
下面是程序运行的效果:
以上则是咱们的回声服务程序,记得本身动手练习哦,眼过千遍不如手过一遍!
本人会持续分享一些关于编程以及编程自学相关的文章,记录本身的自学编程之路。同时但愿本身的分享可以帮助一些对编程感兴趣以及正在编程道路上的朋友。欢迎你们关注个人公众号「阿毛的Coding之路 」。