首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于 Revolt 非阻塞套接字连接/服务器实现

基于 Revolt 非阻塞套接字连接/服务器实现

作者头像
Tinywan
发布2025-07-02 18:40:24
发布2025-07-02 18:40:24
7200
代码可运行
举报
文章被收录于专栏:开源技术小栈开源技术小栈
运行总次数:0
代码可运行

介绍

AMPHP 是一组事件驱动的 PHP 库,在设计时考虑了纤维和并发性。 AMPHP/Socket 是一个用于建立和加密非阻塞套接字的库。它为 Client 端和服务器提供套接字抽象。它抽象了 PHP 中非常低级别的非阻塞流。

安装

代码语言:javascript
代码运行次数:0
运行
复制
composer require amphp/socket

连接到服务器

代码语言:javascript
代码运行次数:0
运行
复制
// You can customize connect() options using ConnectContext
$connectContext = (new Amp\Socket\ConnectContext)
        ->withConnectTimeout(5);

// You can optionally pass a Cancellation object to cancel a pending connect() operation
$deferredCancellation = new Amp\DeferredCancellation();

$socket = connect('amphp.org:80', $connectContext, $deferredCancellation->getCancellation());

处理连接

Socket实现了ReadableStreamWritableStream,因此amphp/byte-stream中的所有内容都适用于接收和发送数据。

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env php
<?php // basic (and dumb) HTTP client

require __DIR__ . '/../vendor/autoload.php';

// This is a very simple HTTP client that just prints the response without parsing.
// league/uri required for this example.

use Amp\ByteStream;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;
use League\Uri\Http;
use function Amp\Socket\connect;
use function Amp\Socket\connectTls;

$stdout = ByteStream\getStdout();

if (\count($argv) !== 2) {
    $stdout->write('Usage: examples/simple-http-client.php <url>' . PHP_EOL);
    exit(1);
}

$uri = Http::createFromString($argv[1]);
$host = $uri->getHost();
$port = $uri->getPort() ?? ($uri->getScheme() === 'https' ? 443 : 80);
$path = $uri->getPath() ?: '/';

$connectContext = (new ConnectContext)
        ->withTlsContext(new ClientTlsContext($host));

$socket = $uri->getScheme() === 'http'
        ? connect($host . ':' . $port, $connectContext)
        : connectTls($host . ':' . $port, $connectContext);

$socket->write("GET {$path} HTTP/1.1\r\nHost: $host\r\nConnection: close\r\n\r\n");

ByteStream\pipe($socket, $stdout);

服务器

amphp/socket允许侦听传入的 TCP 连接以及通过 Unix 域套接字的连接。如果您决定启用 TLS,则默认为安全 TLS 设置。

侦听和接受连接

使用Amp\Socket\Socket\listen()监听端口或 unix 域套接字。它是一个stream_socket_server的包装器,通过异常提供有关失败的有用错误消息。

一旦你开始监听,使用Server::accept()接受客户端。它返回一个Socket,该 Socket 在接受新客户端后返回。它通常在while循环中调用:

代码语言:javascript
代码运行次数:0
运行
复制
$server = Socket\listen("tcp://127.0.0.1:1337");

while ($client = $server->accept()) {
    // You shouldn't spend too much time here, because that blocks accepting another client, so we use async():
    async(function () use ($client) {
        // Handle client connection here
    });
}

基础使用

来实现一个简单的http服务端和客户端

服务端 simple-http-server.php

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env php
<?php declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';

use Amp\Socket;
use function Amp\async;

$server = Socket\listen('127.0.0.1:8888');

echo'Listening for new connections on ' . $server->getAddress() . ' ...' . PHP_EOL;
echo'Open your browser and visit http://' . $server->getAddress() . '/' . PHP_EOL;

while ($socket = $server->accept()) {
    async(function () use ($socket) {
        $address = $socket->getRemoteAddress();
        assert($address instanceof Socket\InternetAddress);

        $ip = $address->getAddress();
        $port = $address->getPort();

        echo"Accepted connection from {$address}." . PHP_EOL;

        $body = "Hey, your IP is {$ip} and your local port used is {$port}." . PHP_EOL;
        $bodyLength = strlen($body);

        $socket->write("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: {$bodyLength}\r\n\r\n{$body}");
        $socket->end();
    });
}

启动服务端

代码语言:javascript
代码运行次数:0
运行
复制
# php simple-http-server.php

Listening for new connections on 127.0.0.1:8888 ...
Open your browser and visit http://127.0.0.1:8888/
Accepted connection from 127.0.0.1:33184.

客户端 simple-http-client.php

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env php
<?php declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';

use Amp\ByteStream;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;
use League\Uri\Http;
use function Amp\Socket\connect;
use function Amp\Socket\connectTls;

$stdout = ByteStream\getStdout();
if (count($argv) !== 2) {
    $stdout->write('Usage: examples/simple-http-client.php <url>' . PHP_EOL);
    exit(1);
}

$uri = Http::new($argv[1]);
$host = $uri->getHost();
$port = $uri->getPort() ?? ($uri->getScheme() === 'https' ? 443 : 80);
$path = $uri->getPath() ?: '/';

$connectContext = (new ConnectContext)
    ->withTlsContext(new ClientTlsContext($host));

$socket = $uri->getScheme() === 'http'
    ? connect($host . ':' . $port, $connectContext)
    : connectTls($host . ':' . $port, $connectContext);

$socket->write("GET {$path} HTTP/1.1\r\nHost: $host\r\nConnection: close\r\n\r\n");

ByteStream\pipe($socket, $stdout);

启动服务端

代码语言:javascript
代码运行次数:0
运行
复制
# php simple-http-client.php http://127.0.0.1:8888

HTTP/1.1 200 OK
Connection: close
Content-Length: 61

Hey, your IP is 127.0.0.1 and your local port used is 33186.
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 安装
    • 处理连接
    • 服务器
    • 侦听和接受连接
  • 基础使用
    • 服务端 simple-http-server.php
    • 客户端 simple-http-client.php
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档