使用PHP创建一个socket服务端
与常规web开发不同,使用socket开发可以摆脱http的限制。可自定义协议,使用长连接、PHP代码常驻内存等。学习资料来源于workerman官方视频与文档.
通常创建一个socket服务包括这几个简单的步骤:
1.创建一个socket套接字,监听在某协议的某个端口,如:tcp的9865端口,为了是外网可以访问,地址为0.0.0.0,监听地址应为这种格式tcp://0.0.0.0:9865
2.将监听socket设置为非阻塞,若不设置,程序会在客户端连接没有发消息时阻塞。
3.程序阻塞在I/0复用函数stream_select,一旦有读取到的新事件则进行处理。
4.处理客户端发送的数据。若读取的socket连接为监听socket表示有新的连接,否则为当前连接发送了数据。若读取到空或返回了false,则表示客户端断开。
一个简单的demo:
<?php
class Worker{
//监听socket
protected $socket = NULL;
//所有的socket连接
protected $allSockets = array();
//连接事件回调
public $onConnect = NULL;
//断线事件回调
public $onClose = NULL;
//接收消息事件回调
public $onMessage = NULL;
public function __construct($socket_address) {
//创建一个socket监听
$this->socket = stream_socket_server($socket_address);
//设置为非阻塞
stream_set_blocking($this->socket, 0);
//将socket监听加入allSockets
$this->allSockets[(int)$this->socket] = $this->socket;
}
public function run() {
while(true) {
//不监听可写事件与带外数据事件
$write = $except = array();
//监听所有的socket事件
$read = $this->allSockets;
//整个进程阻塞在这里,持续监听可读事件
//此处参数均为引用传递,在函数中会改变传值
stream_select($read, $write, $except, 60);
//处理所有可读事件
foreach ($read as $index => $socket) {
//如果是监听socket,此处表示有新的连接
if ($socket === $this->socket) {
//通过stream_socket_accept获取新的连接
$new_conn_socket = stream_socket_accept($socket);
if ($this->onConnect) {
//触发连接事件的回调,并将当前连接传递给回掉函数
call_user_func($this->onConnect, $socket);
}
//记录此socket连接,以便于sream_select监听可读事件
$this->allSockets[(int)$new_conn_socket] = $new_conn_socket;
} else
//如果可读事件不为监听socket,则表示对应客户端有数据发过来
{
//从连接中读取数据
$buffer = fread($socket, 65535);
//如果数据为空,表示客户端已经断开连接
if ('' === $buffer || false === $buffer) {
//尝试触发onClose回调
if ($this->onClose) {
call_user_func($this->onClose, $socket);
}
fclose($socket);
//关闭socket连接并从allSockets中删除
unset($this->allSockets[(int)$socket]);
continue;
}
//表示一个正常的连接,已经读取到消息,交给回掉函数处理
if ($this->onMessage) {
call_user_func($this->onMessage, $socket, $buffer);
}
}
}
}
}
}
$worker = new Worker('tcp://0.0.0.0:9865');
$worker->onConnect = function ($conn) {
echo '新的连接来了';
};
$worker->onClose = function ($conn) {
echo '连接断开了';
};
$worker->onMessage = function ($conn, $message) {
$http_resonse = "HTTP/1.1 200 OK\r\n";
$http_resonse .= "Connection: keep-alive\r\n";
$http_resonse .= "Server: php socket server\r\n";
$http_resonse .= "Content-length: 11\r\n\r\n";
$http_resonse .= "hello world";
fwrite($conn, $http_resonse);
};
$worker->run();
在cli环境下运行脚本:$ php worker.php
,
然后使用浏览器访问本地的9865端口即可看到我们的hello world
使用PHP创建一个socket服务端的更多相关文章
- [Swift通天遁地]四、网络和线程-(14)创建一个Socket服务端
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 第一个socket服务端程序
第一个socket服务端程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include ...
- 创建一个socket服务实时统计在线人数
主要是两个文件,一个是后端文件,一个是前端文件: 后端文件:有人登录了,就通知所有的正在访问的页面,把总人数+1:反之-1: 前端文件:有人登录了,通知后端,页面关闭了,通知后端,同时接收后端派发来的 ...
- netty(二) 创建一个netty服务端和客户端
服务端 NettyServer package com.zw.netty.config; import com.zw.netty.channel.ServerInitializer;import io ...
- [Swift通天遁地]四、网络和线程-(13)创建一个Socket客户端
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 使用NewLife网络库构建可靠的自动售货机Socket服务端(一)
最近有个基于tcp socket 协议和设备交互需求,想到了新生命团队的各种组件,所以决定用NewLife网络库作为服务端来完成一系列的信息交互. 第一,首先说一下我们需要实现的功能需求吧 1,首先客 ...
- C# Socket服务端与客户端通信(包含大文件的断点传输)
步骤: 一.服务端的建立 1.服务端的项目建立以及页面布局 2.各功能按键的事件代码 1)传输类型说明以及全局变量 2)Socket通信服务端具体步骤: (1)建立一个Socket (2)接收 ...
- 适合新手:从零开发一个IM服务端(基于Netty,有完整源码)
本文由“yuanrw”分享,博客:juejin.im/user/5cefab8451882510eb758606,收录时内容有改动和修订. 0.引言 站长提示:本文适合IM新手阅读,但最好有一定的网络 ...
- 创建APPID&&部署服务端教程
创建APPID&&部署服务端 一.创建APPID 1.打开https://console.developers.google.com ,左击顶部Project,然后左击创建项目 2.输 ...
随机推荐
- Java中Vector与ArrayList的差别具体解释
首先看这两类都实现List接口,而List接口一共同拥有三个实现类.各自是ArrayList.Vector和LinkedList.List用于存放多个元素,可以维护元素的次序,而且同意元素的反复. 3 ...
- BIEE-CSS样式大全
字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...
- DLL内存分配与共享
一旦DLL的文件映像被映射到调用进程的地址空间中,DLL的函数就可以供进程中运行的所有线程使用.实际上,DLL几乎将失去它作为DLL的全部特征.对于进程中的线程来说,DLL的代码和数据看上去就像恰巧是 ...
- 通过Jenkins部署java项目
部署java项目-创建私有仓库 Jenkins大多数情况下都是用来部署Java项目,Java项目有一个特点是需要编译和打包的,一般情况下编译和打包都是用maven完成,所以系统环境中需要安装maven ...
- python challenge答案参考
Solutions to python challenge. http://garethrees.org/2007/05/07/python-challenge/ https://github.com ...
- Windows网络配置脚本
静态ip和动态ip切换 适用于:公司学校家庭的网络环境切换[请修改具体ip地址] ::ip for win7.bat::win8以上请用ipv4替换ip @echo off 设置为静态IP 设置为动态 ...
- Parallel小记
List<Temp> tList = new List<Temp>(); ; i < ; i++) { tList.Add(new Temp() { id = i, na ...
- 改变Fragment的默认动画
FragmentTransaction ft = getFragmentManager().beginTransaction(); //设置进入退出动画 ft.setCustomAnimations( ...
- 构建基于Javascript的移动web CMS入门——简单介绍
看到项目上的移动框架,网上寻找了一下,发现原来这些一開始都有. 于是,找了个演示样例開始构建一个移动平台的CMS--墨颀 CMS,方便项目深入理解的同一时候.也能够自己维护一个CMS系统. 构建框架 ...
- Nginx负载均衡和LVS负载均衡的比较分析(转)
Nginx负载均衡和LVS负载均衡的比较分析 作者:匿名 来源:ChinaZ源码报导 浏览:1032次 2011-12-6 15:12:27 字号:大 中 小 [摘要]Nginx是一个高性能的 HTT ...