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

栏目: 服务器 · 发布时间: 5年前

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

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

概述

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

理论

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

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

第一步

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

第二步

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

第三步

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

实践

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

函数

点击函数了解用法

代码

废话少说直接开撸~

<?php
 class Worker{
     //监听socket
     protected $socket = NULL;
     //连接事件回调
     public $onConnect = NULL;
     //接收消息事件回调
     public $onMessage = NULL;
     public function __construct($socket_address) {

     }

     public function run(){

     }
 }



$worker = new Worker('tcp://0.0.0.0:9810');
//提前注册了一个连接事件回调
$worker->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\r\n";
         $http_resonse .= "Content-Type: text/html;charset=UTF-8\r\n";
         $http_resonse .= "Connection: keep-alive\r\n";
         $http_resonse .= "Server: php socket server\r\n";
         $http_resonse .= "Content-length: ".strlen($content)."\r\n\r\n";
         $http_resonse .= $content;
         fwrite($conn, $http_resonse);
     }
 }

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

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

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

缺点

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


以上所述就是小编给大家介绍的《(一)如何实现一个单进程阻塞的网络服务器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

增长的本质

增长的本质

凯萨·伊达尔戈 / 中信出版集团股份有限公司 / 2015-11-1 / CNY 49.00

这是一本物理学家撰写得跨经济学、社会、物理学等多学科的专著。在伊达尔戈之前,从来没有人以这样的方式研究经济增长。 什么是经济增长?为什么它只发生在历史长河的一些节点上?传统意义上的解释都强调了体制、地理、金融和心理因素。而塞萨尔?伊达尔戈告诉我们,想了解经济增长的本质,还需要走出社会科学的研究,在信息、关系网和复杂性这样的自然科学中寻求答案。为了认识经济发展,塞萨尔?伊达尔戈认为我们首先需要......一起来看看 《增长的本质》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具