Simple and lightweight OOP wrapper for PHP's low-level sockets extension (ext-sockets)

Overview

clue/socket-raw

CI status installs on Packagist

Simple and lightweight OOP wrapper for PHP's low-level sockets extension (ext-sockets).

PHP offers two networking APIs, the newer streams API and the older socket API. While the former has been a huge step forward in generalizing various streaming resources, it lacks some of the advanced features of the original and much more low-level socket API. This lightweight library exposes this socket API in a modern way by providing a thin wrapper around the underlying API.

  • Full socket API - It exposes the whole socket API through a sane object-oriented interface. Provides convenience methods for common operations as well as exposing all underlying methods and options.
  • Fluent interface - Uses a fluent interface so you can easily chain method calls. Error conditions will be signalled using Exceptions instead of relying on cumbersome return codes.
  • Lightweight, SOLID design - Provides a thin abstraction that is just good enough and does not get in your way. This library is merely a very thin wrapper and has no other external dependencies.
  • Good test coverage - Comes with an automated test suite and is regularly tested in the real world.

Table of contents

Support us

We invest a lot of time developing, maintaining and updating our awesome open-source projects. You can help us sustain this high-quality of our work by becoming a sponsor on GitHub. Sponsors get numerous benefits in return, see our sponsoring page for details.

Let's take these projects to the next level together! 🚀

Quickstart example

Once installed, you can use the following example to send and receive HTTP messages:

read(8192)); $socket->close(); ">
$factory = new \Socket\Raw\Factory();

$socket = $factory->createClient('www.google.com:80');
echo 'Connected to ' . $socket->getPeerName() . PHP_EOL;

// send simple HTTP request to remote side
$socket->write("GET / HTTP/1.1\r\n\Host: www.google.com\r\n\r\n");

// receive and dump HTTP response
var_dump($socket->read(8192));

$socket->close();

See also the examples.

Usage

Factory

As shown in the quickstart example, this library uses a Factory pattern as a simple API to socket_create(). It provides simple access to creating TCP, UDP, UNIX, UDG and ICMP protocol sockets and supports both IPv4 and IPv6 addressing.

$factory = new \Socket\Raw\Factory();

createClient()

The createClient(string $address, null|float $timeout): Socket method is the most convenient method for creating connected client sockets (similar to how fsockopen() or stream_socket_client() work).

// establish a TCP/IP stream connection socket to www.google.com on port 80
$socket = $factory->createClient('tcp://www.google.com:80');

// same as above, as scheme defaults to TCP
$socket = $factory->createClient('www.google.com:80');

// same as above, but wait no longer than 2.5s for connection
$socket = $factory->createClient('www.google.com:80', 2.5);

// create connectionless UDP/IP datagram socket connected to google's DNS
$socket = $factory->createClient('udp://8.8.8.8:53');

// establish TCP/IPv6 stream connection socket to localhost on port 1337
$socket = $factory->createClient('tcp://[::1]:1337');

// connect to local Unix stream socket path
$socket = $factory->createClient('unix:///tmp/daemon.sock');

// create Unix datagram socket
$socket = $factory->createClient('udg:///tmp/udg.socket');

// create a raw low-level ICMP socket (requires root!)
$socket = $factory->createClient('icmp://192.168.0.1');

createServer()

The createServer($address) method can be used to create a server side (listening) socket bound to specific address/path (similar to how stream_socket_server() works). It accepts the same addressing scheme as the createClient() method.

// create a TCP/IP stream connection socket server on port 1337
$socket = $factory->createServer('tcp://localhost:1337');

// create a UDP/IPv6 datagram socket server on port 1337
$socket = $factory->createServer('udp://[::1]:1337');

create*()

Less commonly used, the Factory provides access to creating (unconnected) sockets for various socket types:

$socket = $factory->createTcp4();
$socket = $factory->createTcp6();

$socket = $factory->createUdp4();
$socket = $factory->createUdp6();

$socket = $factory->createUnix();
$socket = $factory->createUdg();

$socket = $factory->createIcmp4();
$socket = $factory->createIcmp6();

You can also create arbitrary socket protocol types through the underlying mechanism:

$factory->create($family, $type, $protocol);

Socket

As discussed above, the Socket class is merely an object-oriented wrapper around a socket resource. As such, it helps if you're familar with socket programming in general.

The recommended way to create a Socket instance is via the above Factory.

Methods

All low-level socket operations are available as methods on the Socket class.

You can refer to PHP's fairly good socket API documentation or the docblock comments in the Socket class to get you started.

Data I/O:
$socket->write('data');
$data = $socket->read(8192);
Unconnected I/O:
$socket->sendTo('data', $flags, $remote);
$data = $socket->rcvFrom(8192, $flags, $remote);
Non-blocking (async) I/O:
$socket->setBlocking(false);
$socket->selectRead();
$socket->selectWrite();
Connection handling:
$client = $socket->accept();
$socket->bind($address);
$socket->connect($address);
$socket->shutdown();
$socket->close();

Install

The recommended way to install this library is through Composer. New to Composer?

This project follows SemVer. This will install the latest supported version:

$ composer require clue/socket-raw:^1.5

See also the CHANGELOG for details about version upgrades.

This project aims to run on any platform and thus does not require any PHP extensions besides ext-sockets and supports running on legacy PHP 5.3 through current PHP 8+. It's highly recommended to use PHP 7+ for this project.

Tests

To run the test suite, you first need to clone this repo and then install all dependencies through Composer:

$ composer install

To run the test suite, go to the project root and run:

$ php vendor/bin/phpunit

Note that the test suite contains tests for ICMP sockets which require root access on Unix/Linux systems. Therefor some tests will be skipped unless you run the following command to execute the full test suite:

$ sudo php vendor/bin/phpunit

The test suite also contains a number of functional integration tests that rely on a stable internet connection. If you do not want to run these, they can simply be skipped like this:

$ php vendor/bin/phpunit --exclude-group internet

License

This project is released under the permissive MIT license.

Did you know that I offer custom development services and issuing invoices for sponsorships of releases and for contributions? Contact me (@clue) for details.

Comments
  • Added phpunit to composer dev dependencies

    Added phpunit to composer dev dependencies

    I am keen to start contributing as I'm about to begin using this library for a project I'm working on.

    I don't have phpunit installed globally and since it now supports being installed with composer, I've added it as a dev dependency to make it easier to run the tests in this project.

    maintenance 
    opened by ascii-soup 8
  • Socket recv should return the number of bytes read rather than the buffer

    Socket recv should return the number of bytes read rather than the buffer

    One of the advantages of socket_recv is it returns the length of the data for you. I believe that method should take the $buffer parameter by ref and return the length as the php function does.

    opened by mrrsm 8
  • socket_select accepts only integers

    socket_select accepts only integers

    https://www.php.net/manual/en/function.fmod

            $usec = $sec === null ? null : fmod($sec, 1) * 1e6;
    
            $ret = @socket_select($r, $w, $e, (int)$sec, (int)$usec);
    

    What do you think about this?

    easy pick 
    opened by szepeviktor 6
  • Skip IPv6 tests for Travis CI

    Skip IPv6 tests for Travis CI

    IPv6 no longer present The major change that is coming with this migration is that local and external IPv6 networking will no longer be present. This has been present and while technically not considered to be a feature, it has been available. With the move to GCE this will no longer work, until such time as as GCE adds IPv6 support. We do understand this may cause a disruption for some use cases and while we have considered numerous ways to try to provide IPv6 in the cloud, none of the current available options are suitable for a large production deployment. We ask for your understanding and patience with the fact that is will no be supported for the near future.

    https://blog.travis-ci.com/2015-11-27-moving-to-a-more-elastic-future

    help wanted maintenance 
    opened by clue 6
  • "Socket operation failed: Success"

    Just very short, because it's already late here.

    I sometimes see this uncaught exception

    PHP Fatal error: Uncaught exception 'Socket\Raw\Exception' with message 'Socket operation failed: Success'

    The "Success" is already strange on it's own. It seems, that this is related to non-blocking streams. The error code is 0 and I couldn't find any reference to this error code, so I assume, that the manual is in this case not very accurate and all functions can also return false simply if they don't have something to return.

    bug help wanted 
    opened by KingCrunch 5
  • IPv6 tests are now skipped on Travis CI

    IPv6 tests are now skipped on Travis CI

    Should fix #25

    I've pulled the environment tests (unix + ipv6) into their own object and used this inside the Factory tests.

    If this is merged, should we utilise the new Environment object inside the Factory itself? For instance, throwing a custom exception inside createTcp6() with a nice message stating that IPv6 support is not available.

    I've left the TODO markers next to their respective checks - what can be done to test these checks thoroughly

    opened by ascii-soup 4
  • How to send POST

    How to send POST

    So, I'm trying to send POST to a server with your lib, but I don't know what am I missing while writing data to host... $socket->write( "POST /test.php?var=1 HTTP/1.1rn" ); $socket->write( "Host: localhostrn" ); $socket->write( "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0rn" ); $socket->write( "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8rn" ); $socket->write( "Accept-Language: pl,en-us;q=0.7,en;q=0.3rn" ); $socket->write( "Accept-Encoding: gzip, deflatern" ); $socket->write( "Cookie: " . $cookie . "rn" ); $socket->write( "Connection: keep-alivern" ); $socket->write( "rn" );

    opened by mrWodoo 4
  • socket timeout reply

    socket timeout reply

    Hi, i'm using the library with udp sockets, every works perfectly, but sometimes the server reply (ack) is lost and the script is left waiting for a reply.

    I've set the timeout value, but it seems it's only set when creating the socket.

    Anyone might know what i'm missing?

    Thanks to all

    question 
    opened by eduardor2k 3
  • suppress warning error logs for assertAlive

    suppress warning error logs for assertAlive

    with a third party library (https://github.com/jonjomckay/quahog) we get this stack trace:

    vendor/sentry/sentry/lib/Raven/ErrorHandler.php in socket_last_error vendor/clue/socket-raw/src/Exception.php in createFromSocketResource at line 21 vendor/clue/socket-raw/src/Socket.php in getOption at line 176 vendor/clue/socket-raw/src/Socket.php in assertAlive at line 478

    it is a E_WARNING caused by assertAlive() socket operation on an invalid resource. Added error handling code to avoid raising E_WARNINGs in assertAlive()

    bug help wanted 
    opened by paulmhh 3
  • Factory has a number of undefined variables

    Factory has a number of undefined variables

    My IDE reveals the Factory class has two cases where an undefined variable is used, $scheme. I think this is used for write-back, but nevertheless it will raise a notice unnecessarily. This can be fixed by setting the var to something prior to using it:

    $scheme = null; // Prevents 'Undefined variable' notice
    $socket = $this->createFromString($address, $scheme);
    

    I can send a PR if that is helpful.

    question help wanted 
    opened by halfer 3
  • Multiple clients not connecting

    Multiple clients not connecting

    So I am creating server and connecting multiple clients

    Server.PHP

    <?php
    include_once 'vendor/autoload.php';
    $factory = new \Socket\Raw\Factory();
    $socket = $factory->createServer('localhost:9999');
    $socket->listen(10);
    echo "Waiting for incoming connections... \n";
    
    while(1) {
        $client = $socket->accept();
        $client_info = $client->getPeerName();
        if($client_info != null) {
            print 'Connect Client :-'.$client_info."\n";     
        }
        $data = $client->read(1024000);
        print $data."\n";
        $client->write('Agent said: '.$data);
    }
    

    Client

    <?php
    include_once 'vendor/autoload.php';
    $factory = new \Socket\Raw\Factory();
    
    $socket = $factory->createClient('localhost:9999');
    echo 'Connected to ' . $socket->getPeerName() . PHP_EOL;
    
    $index = 0;
    
    
    // receive and dump HTTP response
    //var_dump($socket->read(8192));
    while(1) {
    $socket->write("Client is here \n");
    }
    

    When I execute the code it just connects one client and in Server window it shows entry of one client only as Connect Client :-127.0.0.1:63031

    2nd , only sending data it throws error:

    Fatal error: Uncaught exception 'Socket\Raw\Exception' with message 'Socket operation failed: Broken pipe (SOCKET_EPIPE)' in /abc/Server/vendor/clue/socket-raw/src/Exception.php:55
    
    question 
    opened by kadnan 3
Releases(v1.6.0)
  • v1.6.0(Apr 14, 2022)

    • Feature: Forward compatibility with PHP 8.1 release. (#67 and #68 by @clue)

    • Fix: Fix reporting refused connections on Windows. (#69 by @clue)

    • Improve CI setup and documentation. (#70 and #65 by @clue, #64 by @szepeviktor and #66 by @PaulRotmann)

    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Nov 27, 2020)

    • Feature: Support PHP 8 and drop legacy HHVM support. (#60 and #61 by @clue)

    • Improve test suite and add .gitattributes to exclude dev files from export. Update to PHPUnit 9 and simplify test matrix. (#50, #51, #58 and #63 by @clue and #57 by @SimonFrings)

    Source code(tar.gz)
    Source code(zip)
  • v1.4.1(Oct 28, 2019)

    • Fix: Fix error reporting when invoking methods on closed socket instance. (#48 by @clue)

    • Improve test suite to run tests on Windows via Travis CI. (#49 by @clue)

    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Jan 22, 2019)

    • Feature: Improve Windows support (async connections and Unix domain sockets). (#43 by @clue)

    • Improve test suite by adding forward compatibility with PHPUnit 7 and PHPUnit 6. (#42 by @clue)

    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Jun 10, 2018)

    • Feature: Add $timeout parameter for Factory::createClient() (#39 by @Elbandi and @clue)

      // connect to Google, but wait no longer than 2.5s for connection
      $socket = $factory->createClient('www.google.com:80', 2.5);
      
    • Improve test suite by adding PHPUnit to require-dev, update test suite to test against legacy PHP 5.3 through PHP 7.2 and optionally skip functional integration tests requiring internet. (#26 by @ascii-soup, #28, #29, #37 and #38 by @clue)

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Mar 18, 2015)

  • v1.1.0(Oct 24, 2014)

    • Feature: Accept float timeouts like 0.5 for Socket::selectRead() and Socket::selectWrite(). (#8)
    • Feature: Add new Socket::connectTimeout() method. (#11)
    • Fix: Close invalid socket resource when Factory fails to create a Socket. (#12)
    • Fix: Calling accept() on an idle server socket emits right error code and message. (#14)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(May 11, 2014)

  • v0.1.2(May 10, 2014)

    • Fix: The Factory::createUdg() now returns the right socket type.
    • Fix: Fix ICMPv6 addressing to not require square brackets because it does not use ports.
    • Extended test suite.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(May 10, 2014)

  • v0.1.0(May 10, 2014)

Owner
Christian Lück
@reactphp maintainer / Freelance Software Engineer, all things web, passionate about coaching others building awesome things… Reach out if you need help
Christian Lück
Bulit PHP Twitter Clone IN OOP style and using MYSQL Database.

Bulit PHP Twitter Clone IN OOP style and using MYSQL Database. AJAX and Jquery for requests without reloading like Follow/unfollow, like, Search users, Show popups like comment , User lists, etc.

Amin 47 Dec 3, 2022
Examination tasks to test backend knowledge (for junior level)

Task 1 The website of one of our old clients was hacked. After hacking, a strange red bar appeared on the site at the bottom of the page (https://imgu

dev.family 4 Apr 29, 2022
A simple wrapper for PHP Intervention Library to provide a more simple interface and convenient way to convert images to webp

This package is a simple wrapper for PHP Intervention Library to provide a more simple interface and convenient way to convert images to webp - next generation format - extension, and resize them to render only needed sizes.

eyad hamza 18 Jun 28, 2022
Simple and Lightweight PHP Class & Methods Annotations Reader

README Simple and Lightweight PHP Class & Methods Annotations Reader Forked from eriknyk/Annotations 项目地址 github https://github.com/phppkg/annotations

PHPPkg 3 Nov 25, 2021
DooTask is a lightweight open source online project task management tool that provides various document collaboration tools, online mind mapping, online flowcharting, project management, task distribution, instant IM, file management and other tools.

DooTask is a lightweight open source online project task management tool that provides various document collaboration tools, online mind mapping, online flowcharting, project management, task distribution, instant IM, file management and other tools.

kuaifan 3k Jan 5, 2023
yxorP is a PHP-based proxy application that is very lightweight and easily customizable per user needs.

Web Proxy Guzzler + SAAS(y) Cockpit (GUI Dashboard incl.). Feature Rich, Multi-tenancy, Headless, Plug & Play, Augmentation & Content Spinning Web Proxy with Caching - PHP CURL+Composer are Optional. Leveraging SAAS architecture to provide multi-tenancy, multiple threads, caching, and an article spinner service.

4D/ҵ.com Dashboards 9 Aug 14, 2022
Mira - A lightweight WebUI alternative to top/htop for GNU/Linux.

Mira Mira lets you monitor your server's resource usage through a responsive WebUI. ======== Introduction Screenshots Installation Limitations Known I

Jams246 9 Mar 27, 2022
An ultra-lightweight blogging engine, written in PHP.

简体中文, Italiano. ?? Translations wanted! Go to the wiki to find out more about translating Chyrp Lite into your language. What can Chyrp Lite do for me

Daniel Pimley 202 Jan 2, 2023
a super lightweight markdown wiki/blog/tweeting system.

laMDWiki is a super light weight blog/wiki platform running on PHP!

null 4 Dec 24, 2021
Laravel wrapper for the Fathom Analytics API

Please note: This package is still a work in progress and the Fathom API is also only in early access. Do not use this package in your production envi

Marc Reichel 12 Sep 19, 2022
Provides an API wrapper for interacting with remote CiviCRM instances via APIv4.

civicrm-api is a Composer package that allows developers to interact with a CiviCRM instance using the REST API v4 functionality within CiviCRM.

Circle Interactive 1 Apr 4, 2022
Simple-podcast-generator - 👉 A very simple way to host your podcast files and generate the RSS Podcast feed 🎙

Podcast RSS Feed Generator A very simple way to host your podcast files and generate the RSS Podcast feed ?? ?? Contents Summary Requirements Installa

♚ PH⑦ de Soria™♛ 11 Dec 2, 2022
Simple-cache - PHP FIG Simple Cache PSR

PHP FIG Simple Cache PSR This repository holds all interfaces related to PSR-16. Note that this is not a cache implementation of its own. It is merely

PHP-FIG 8k Jan 3, 2023
Created simple login system and chat type website using mysql database along with php and html , css and javascript.

Created simple login system and chat type website using mysql database along with php and html , css and javascript.

null 1 Jan 6, 2022
TinyFileManager is web based file manager and it is a simple, fast and small file manager with a single file, multi-language ready web application

TinyFileManager is web based file manager and it is a simple, fast and small file manager with a single file, multi-language ready web application for storing, uploading, editing and managing files and folders online via web browser. The Application runs on PHP 5.5+, It allows the creation of multiple users and each user can have its own directory and a build-in support for managing text files with cloud9 IDE and it supports syntax highlighting for over 150+ languages and over 35+ themes.

Prasath Mani 3.5k Jan 7, 2023
Bolt is a simple CMS written in PHP. It is based on Silex and Symfony components, uses Twig and either SQLite, MySQL or PostgreSQL.

⚠️ Note - Not the latest version This is the repository for Bolt 3. Please know that Bolt 5 has been released. If you are starting a new project, plea

Bolt 4.1k Dec 27, 2022
Modern, simple and fresh looking glass based on Bootstrap 5 and PHP 7

Modern, simple and fresh looking glass based on Bootstrap 5 and PHP 7. A looking glass is a network utility which is made user-friendly for everyone to use. It allows you to execute network related commands within a remote network, usually that of an ISP.

Hybula 77 Jan 1, 2023
Koel is a simple web-based personal audio streaming service written in Vue and Laravel

Koel (also stylized as koel, with a lowercase k) is a simple web-based personal audio streaming service written in Vue on the client side and Laravel on the server side. Targeting web developers, Koel embraces some of the more modern web technologies – CSS grid, audio, and drag-and-drop API to name a few – to do its job.

Koel 14.3k Jan 4, 2023
A simple, beautiful, mobile-first instant messaging web application backend build with ThinkPHP6 and Swoole.

OnChat A simple, beautiful, mobile-first instant messaging progressive web application build with ThinkPHP6 and Swoole. You can click here to view the

HyperLifelll9 138 Dec 26, 2022