资讯专栏INFORMATION COLUMN

(一)如何实现一个单进程阻塞的网络服务器

xiao7cn / 610人阅读

摘要:理论主要介绍下实现一个网络服务器的基本步骤,代码会在实践环节复现一次。第一步我们需要创建一个,绑定服务器端口,监听端口,在中用一个函数就能完成上面个步骤。此时程序会进入睡眠状态,直到有新的客户端发起到服务器,操作系统会唤醒此进程。

概述

想要更好的理解,网络编程,写出一个高性能的服务,我们需要花点时间来理解下对于服务器处理客户端的整个流程并且理解一些关键的术语,本来想在本文中补充一些基础理论知识,担心篇幅过长不利于阅读,所以以后补发一些基础知识,接下来进入正题。

理论

主要介绍下实现一个网络服务器的基本步骤,代码会在实践环节复现一次。

第一步

我们需要创建一个socket,绑定服务器端口(bind),监听端口(listen),在PHP中用stream_socket_server一个函数就能完成上面3个步骤。

第二步

进入while循环,阻塞在accept操作上,等待客户端连接进入。此时程序会进入睡眠状态,直到有新的客户端发起connect到服务器,操作系统会唤醒此进程。accept函数返回客户端连接的socket

第三步

利用fread读取客户端socket当中的数据收到数据后服务器程序进行处理然后使用fwrite向客户端发送响应。长连接的服务会持续与客户端交互,而短连接服务一般收到响应就会close。

实践

在这里我们用代码来实现下基本一个流程,在开始写代码之前介绍介几个php函数,是我们代码中可能会用到的,方便大家理解。

函数

stream_socket_server
stream_socket_accept
call_user_func
is_callable
fread

点击函数了解用法
代码

废话少说直接开撸~

onConnect = function ($data) {
    echo "新的连接来了", $data, PHP_EOL;
};
//提前注册了一个接收消息事件回调
$worker->onMessage = function ($conn, $message) {
};
$worker->run();

按照之前的流程我们需要监听端口+地址

public function __construct($socket_address) {
         //监听地址+端口
         $this->socket=stream_socket_server($socket_address);
     }

下一步就需要阻塞在accept操作,等待客户端连接进入。此时程序会进入睡眠状态,直到有新的客户端发起connect到服务器,操作系统会唤醒此进程

public function run(){
        while (true) { //循环监听
         $client = stream_socket_accept($this->socket);//在服务端阻塞监听
        }
     }

当新的连接进入唤醒进程并且触发连接事件回调

 public function run(){
        while (true) { //循环监听
         $client = stream_socket_accept($this->socket);//在服务端阻塞监听
         if(!empty($client) && is_callable($this->onConnect)){//socket连接成功并且是我们的回调
             //触发事件的连接的回调
             call_user_func($this->onConnect,$client);
         }
        }
     }

这里的连接回调实际上触发的就是之前准备好类库的这里下面这段代码

$worker->onConnect = function ($data) {
    echo "连接事件:", $data, PHP_EOL;
};

当连接成功后利用fread获取到客户端的内容,并触发接收消息事件

     public function run(){
      while (true) { //循环监听
         $client = stream_socket_accept($this->socket);//在服务端阻塞监听
         if(!empty($client) && is_callable($this->onConnect)){//socket连接成功并且是我们的回调
             //触发事件的连接的回调
             call_user_func($this->onConnect,$client);
         }
         //从连接中读取客户端内容
         $buffer=fread($client,65535);//参数2:在缓冲区当中读取的最大字节数
         //正常读取到数据。触发消息接收事件,进行响应
         if(!empty($buffer) && is_callable($this->onMessage)){
             //触发时间的消息接收事件
             call_user_func($this->onMessage,$this,$client,$buffer);//传递到接收消息事件》当前对象、当前连接、接收到的消息
         }
       }
     }

到此处基本的一个网络服务接收基本完成,还需要对请求做出一个响应,以HTTP请求为例,这里封装了一个http响应的方法(http://127.0.0.1:9810)

 class Worker{
    ...
    ...
    ...
     public function  send($conn,$content){
         $http_resonse = "HTTP/1.1 200 OK
";
         $http_resonse .= "Content-Type: text/html;charset=UTF-8
";
         $http_resonse .= "Connection: keep-alive
";
         $http_resonse .= "Server: php socket server
";
         $http_resonse .= "Content-length: ".strlen($content)."

";
         $http_resonse .= $content;
         fwrite($conn, $http_resonse);
     }
 }

当触发接收消息事件时对http请求做出响应

$worker->onMessage = function ($server,$conn, $message) {
    echo "来自客户端消息:",$message,PHP_EOL;
    $server->send($conn,"来自服务端消息");
};

到这就结束了~,完整代码直通车

缺点

一次只能处理一个连接,不支持多个连接同时处理

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30170.html

相关文章

  • 物联网高并发编程之网络编程中线程模型

    摘要:如需了解更多物联网网络编程知识请点击物联网云端开发武器库物联网高并发编程之网络编程中的线程模型值得说明的是,具体选择线程还是进程,更多是与平台及编程语言相关。 如需了解更多物联网网络编程知识请点击:物联网云端开发武器库 物联网高并发编程之网络编程中的线程模型 值得说明的是,具体选择线程还是进程,更多是与平台及编程语言相关。例如 C 语言使用线程和进程都可以(例如 Nginx 使用进程...

    ziwenxie 评论0 收藏0
  • 入门架构——机高性能

    摘要:协作方式在高并发场景中,必须要让服务器同时维护大量请求连接,可能是一个服务进程创建另一个进程,也可能是一个服务线程去创建另一个线程,但连接结束后进程或线程就销毁了,这是一个巨大的浪费一个自然的想法就是通过创建一个进程线程池从而达到资源复用, showImg(https://segmentfault.com/img/bVbtgn1?w=313&h=208); 协作方式 在高并发场景中,必...

    UCloud 评论0 收藏0
  • nginx、swoole高并发原理初探

    摘要:一阅前热身为了更加形象的说明同步异步阻塞非阻塞,我们以小明去买奶茶为例。等奶茶做好了,店员喊一声小明,奶茶好了,然后小明去取奶茶。将响应结果发给相应的连接请求处理完成因为基于,所以每个可以处理无数个连接请求。如此,就轻松的处理了高并发。 一、阅前热身 为了更加形象的说明同步异步、阻塞非阻塞,我们以小明去买奶茶为例。 1、同步与异步 ①同步与异步的理解 同步与异步的重点在消息通知的方式上...

    denson 评论0 收藏0
  • nginx、swoole高并发原理初探

    摘要:一阅前热身为了更加形象的说明同步异步阻塞非阻塞,我们以小明去买奶茶为例。等奶茶做好了,店员喊一声小明,奶茶好了,然后小明去取奶茶。将响应结果发给相应的连接请求处理完成因为基于,所以每个可以处理无数个连接请求。如此,就轻松的处理了高并发。 一、阅前热身 为了更加形象的说明同步异步、阻塞非阻塞,我们以小明去买奶茶为例。 1、同步与异步 ①同步与异步的理解 同步与异步的重点在消息通知的方式上...

    617035918 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<