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

栏目: 服务器 · 发布时间: 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-1-1 / 39.00元

《慕课革命》,国内唯一一本关于全方面了解慕课的权威著作,全面阐述慕课理念与中国实践。 林毅夫、俞敏洪、徐小平、王强作序推。 大规模在线教育的慕课革命大幕已经拉开,这是一场基于互联网及移动互联网的教育大变革。根据网易教育联合有道发起的《2013中国在线教育新趋势调查报告》揭示,中国在线教育正呈现出六大趋势,包括互联网成为人们获取知识的最常见渠道;移动端学习方式已经开始成为人们接受的学习方......一起来看看 《慕课革命》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具