Git Product home page Git Product logo

socket's Introduction

ReactPHP Logo

Event-driven, non-blocking I/O with PHP.

Build Status

ReactPHP is a low-level library for event-driven programming in PHP. At its core is an event loop, on top of which it provides low-level utilities, such as: Streams abstraction, async DNS resolver, network client/server, HTTP client/server and interaction with processes. Third-party libraries can use these components to create async network clients/servers and more.

<?php

// $ composer require react/http react/socket # install example using Composer
// $ php example.php # run example on command line, requires no additional web server

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

$server = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
    return React\Http\Message\Response::plaintext(
        "Hello World!\n"
    );
});

$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$server->listen($socket);

echo "Server running at http://127.0.0.1:8080" . PHP_EOL;

This simple web server written in ReactPHP responds with "Hello World!" for every request.

ReactPHP is production ready and battle-tested with millions of installations from all kinds of projects around the world. Its event-driven architecture makes it a perfect fit for efficient network servers and clients handling hundreds or thousands of concurrent connections, long-running applications and many other forms of cooperative multitasking with non-blocking I/O operations. What makes ReactPHP special is its vivid ecosystem with hundreds of third-party libraries allowing you to integrate with many existing systems, such as common network services, database systems and other third-party APIs.

  • Production ready and battle-tested.
  • Rock-solid with stable long-term support (LTS) releases.
  • Requires no extensions and runs on any platform - no excuses!
  • Takes advantage of optional extensions to get better performance when available.
  • Highly recommends latest version of PHP 7+ for best performance and support.
  • Supports legacy PHP 5.3+ and HHVM for maximum compatibility.
  • Well designed and reusable components.
  • Decoupled parts so they can be replaced by alternate implementations.
  • Carefully tested (unit & functional).
  • Promotes standard PSRs where possible for maximum interoperability.
  • Aims to be technology neutral, so you can use your preferred application stack.
  • Small core team of professionals supported by large network of outside contributors.

ReactPHP is non-blocking by default. Use workers for blocking I/O. The event loop is based on the reactor pattern (hence the name) and strongly inspired by libraries such as EventMachine (Ruby), Twisted (Python) and Node.js (V8).

This repository you're currently looking at is mostly used as a meta repository to discuss and plan all things @ReactPHP. See the individual components linked below for more details about each component, its documentation and source code.

Core Components

Network Components

Utility Components

Built with ReactPHP

  • Thruway PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging voryx/Thruway

  • PPM - PHP Process Manager PPM is a process manager, supercharger and load balancer for modern PHP applications. php-pm/php-pm

  • php-ar-drone 🚁 Port of node-ar-drone which allows user to control a Parrot AR Drone over PHP jolicode/php-ar-drone

  • Ratchet Asynchronous WebSocket server ratchetphp/Ratchet

  • Predis\Async Asynchronous PHP client library for Redis built on top of ReactPHP nrk/predis-async

  • clue/redis-server A Redis server implementation in pure PHP clue/redis-server

And many more on our wiki page »

Articles

  • Sergey Zhuk A series of articles covering ReactPHP: from the basics to the real application examples. sergeyzhuk.me

  • Cees-Jan Kiewiet Blog series about several ReactPHP components and how they work. blog.wyrihaximus.net

  • Loïc Faugeron Super Speed Symfony - ReactPHP. gnugat.github.io

  • Marc J. Schmidt Bring High Performance Into Your PHP App (with ReactPHP). marcjschmidt.de

  • Marc Morera When ReactPHP meet Symfony medium.com/@apisearch

Talks

Getting started

ReactPHP consists of a set of individual components. This means that instead of installing something like a "ReactPHP framework", you actually pick only the components that you need.

This project follows SemVer for all its stable components. The recommended way to install these components is through Composer. New to Composer?

For example, this may look something like this:

# recommended install: pick required components
composer require react/event-loop react/http

As an alternative, we also provide a meta package that will install all stable components at once. Installing this is only recommended for quick prototyping, as the list of stable components may change over time. This meta package can be installed like this:

# quick protoyping only: install all stable components
composer require react/react:^1.4

For more details, check out ReactPHP's homepage for quickstart examples and usage details.

See also the combined changelog for all ReactPHP components for details about version upgrades.

Support

Do you have a question and need help with ReactPHP? Don't worry, we're here to help!

As a first step, check the elaborate documentation that comes with each component (see links to individual documentation for each component above). If you find your question is not answered within the documentation, there's a fair chance that it may be relevant to more people. Please do not hesitate to file your question as an issue in the relevant component so others can also participate.

You can also check out our official Gitter chat room. Most of the people involved in this project are available in this chat room, so many questions get answered in a few minutes to some hours. We also use this chat room to announce all new releases and ongoing development efforts, so consider staying in this chat room for a little longer.

Also follow @reactphp on Twitter for updates. We use this mostly for noteworthy, bigger updates and to keep the community updated about ongoing development efforts. You can always use the #reactphp hashtag if you have anything to share!

We're a very open project and we prefer public communication whenever possible, so that more people can participate and help getting the best solutions available. At the same time, we realize that some things are better addressed in private. Whether you just want to say thank you, want to report a security issue or want to help sponsor a certain feature development, you can reach out to the core team in private by sending an email to [email protected]. Please keep in mind that we're a small team of volunteers and do our best to support anybody reaching out.

Do you want to support ReactPHP? Awesome! Let's start with letting the the world know why you think ReactPHP is awesome and try to help others getting on board! Send a tweet, write a blog post, give a talk at your local user group or conference or even write a book. There are many ways you can help. You can always reach out to us in private and help others in our support channels. Thank you!

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:

vendor/bin/phpunit

The test suite also contains a number of functional integration tests that rely on a stable internet connection. Due to the vast number of integration tests, these are skipped by default during CI runs. If you also do not want to run these, they can simply be skipped like this:

vendor/bin/phpunit --exclude-group internet

License

MIT, see LICENSE.

socket's People

Contributors

alexmace avatar andig avatar carusogabriel avatar cboden avatar christiaan avatar clue avatar cn007b avatar daverandom avatar e3betht avatar elliot avatar hansott avatar igorw avatar jsor avatar kelunik avatar mmoreram avatar nhedger avatar reedy avatar robinvdvleuten avatar sgoettschkes avatar simonfrings avatar the-eater avatar tkleinhakisa avatar valga avatar wyrihaximus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

socket's Issues

Error when sending large chunks of data over a secure TLS connection with older PHP versions

Originally reported here: reactphp/stream#64

This can actually easily be reproduced by sending a "large" chunk of data at once over a TLS connection. On my system, this appears to be anything larger than around 30 KB at once passed to the underlying fwrite() call.

error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry

This is actually a bug in PHP that has been reported via https://bugs.php.net/bug.php?id=72333. The bug has been present for years and has been fixed recently via php/php-src@17e9fc9 which landed in 7.1.4 and 7.0.18.

I've played around with different buffers and write chunks and it looks like this can be worked around by limiting the write chunk size to anything smaller than around 8 KB.

Roadmap to stable v1.0.0

Let's face it, this project is stable and has been used in production for years :shipit:

However, we're currently following a v0.X.Y release scheme (http://sentimentalversioning.org/).

We should finally make this explicit and fully adhere to SemVer and release a stable v1.0.0.

To a large extend, a stable v1.0.0 helps making BC breaks more explicit and thus the whole project more reliable from a consumer perspective. This project is actively maintained and has received some major updates in the last weeks and has some major updates planned in the next weeks. Given our current versioning scheme, we'd like to ensure all anticipated BC breaks will be merged before the planned v1.0.0 release.

As such, I've set up a roadmap that enlists only the major changes for each version among with planned release dates towards a stable v1.0.0 release:

v0.5.0 ✅

  • Released 2017-02-14
  • No temporal dependence
  • URIs everywhere
  • Reduce public API

v0.5.1 ✅

  • Released 2017-03-09
  • Update stream component

v0.6.0 ✅

  • Released 2017-04-04
  • Limit connections (pause/resume server)

v0.7.0 ✅

  • Released 2017-04-10
  • Merge SocketClient into this component

v0.8.0 ✅

  • Released 2017-05-09
  • Server facade API
  • Address URIs

v1.0.0

  • Planned 2018-?
  • No new changes planned, this should merely mark the previous release as "stable"

This ticket aims to serve as a basic overview and does not contain every single change. Please also see the milestone links and the CHANGELOG for more details.

Obviously, this roadmap is subject to change and I'll try to keep it updated as we progress. In order to avoid cluttering this, please keep discussion in this ticket to a minimum and consider reaching out to us through new tickets or Twitter etc.

[Client] DNS should have option to use IPv6 (AAAA) records

The Connector (and underlying DnsConnector) is currently hard-coded to only look up IPv4 (A) records from the DNS server. There is currently no way to tell it to look up IPv6 (AAAA) records.

(Note that explicitly connecting to IPv4 and IPv6 addresses works just fine)

We should implement a way to explicitly define the lookup mode and eventually find a way to automatically use the correct mode (figure out if this system prefers or even supports IPv6).

Opening this ticket as a reminder and to spark the discussion - the implementation likely depends on reactphp/dns#43

Cannot bind IPv6 [::] (any)

        $loop = \React\EventLoop\Factory::create();
        $ip4 = new \React\Socket\Server($loop);
        $ip6 = new \React\Socket\Server($loop);
        $ip4->listen(9988, '0.0.0.0');
        $ip6->listen(9988, '::');

        $wsStack = new \Ratchet\Http\HttpServer(
            new WsServer(
                new Online()
            )
        );

        $ip4App = new IoServer($wsStack, $ip4, $loop);
        $ip6App = new IoServer($wsStack, $ip6, $loop);
        $loop->run();

This fails with:
Exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://[::]:9988: Address already in use'

But address is not in use, in fact if I replace :: with the actual machine public IPv6 address works fine.

[Client] Connectors do not honor /etc/hosts

Originally reported 2015-05-31 by @clue: reactphp-legacy/socket-client#35

There's currently no way to connect to "localhost" or any other host names listed in the local /etc/hosts file. We could provide a hard-coded default for some common host names (like "localhost"), but this is bound to break.

In particular, this also affects usage with linked Docker containers where one container references another container by its host name. This means that there's currently no way to connect to other containers by their name.

Opening this ticket as a reminder - this actually depends on reactphp/dns#10

Type annotations misinterpreted by phpstan

When using this library in a project which uses phpstan for code analysis it gives the following error.

Call to method then() on an unknown class     
React\Socket\React\Promise\PromiseInterface. 

This happens because of the following return type @return React\Promise\PromiseInterface of ConnectorInterface#connect

Since the file is namespaced it expects all types to either be relative to the file namespace or to start with a \ if you want a fully qualified name.

Extend ConnectionInterface with ports / target address.

(Related to #26)

I'm implementing the proxy protocol for react:
http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt

Even though not all transports have a separate port part, I think it would be nice to add some more methods to the connection interface:

public function getTargetAddress();
public function getTargetPort();
public function getRemotePort();

-- Part below is about the naming of entities in the connection interface --

Also naming could possibly be reconsidered. Connections always have a direction (source and target), but the concept of local and remote does not always apply. I understand that getRemoteAddress() refers to the "other" end of the connection, but it could be more consistent when we use source and target.
When looking at it from a more abstract viewpoint:

Consider:
Client A connects to Server B to establish a Connection C
Both A and B both have an object representing C, say C_a and C_b
Using terms like remoteAddress and localAddress creates the following relation:

C_a.remoteAddress = C_b.localAddress 
and 
C_a.localAddress = C_b.remoteAddress

When multiple connections are managed, both inbound and outbound, we need to "know" where the connection came from to decide which party we are (local or remote).

Listening on same port twice does not fail on Windows

Test suite for v0.4.4 fails on Windows, using both 5.6.29 and 7.0.13, with PHPUnit 4.8.31

PHPUnit 4.8.31 by Sebastian Bergmann and contributors.

...............F

Time: 21.31 seconds, Memory: 8.00MB

There was 1 failure:

1) React\Tests\Socket\ServerTest::testListenOnBusyPortThrows
Failed asserting that exception of type "React\Socket\ConnectionException" is thrown.

FAILURES!
Tests: 16, Assertions: 15, Failures: 1.

Edit: expanded information to include full phpunit output

header

tell me how to put in the library header?
header ('Access-Control-Allow-Origin: *');
It does not work

Also expose port for each connection

Currently, the Connection::getRemoteAddress() method only returns the IP address of the remote peer.

There's currently no way to access its TCP/IP port.

It's quite trivial to add a getRemotePort() method, but we should think twice about whether we should limit ourselves to TCP/IP here.

Other schemes (such as Unix or perhaps even raw sockets) do not have a concept of "ports" and may not necessarily build on top of IP.

As such, we should consider just returning the full remote peer address from the getRemoteAddress() method.

Ratchet onopen client not fire

I am trying to implement Ratchet Socket Hello word on my local machine every things works perfectly but on vps centos server when i run server service with

ssh Command : php chat-server.php
it start Listening on port correctly(i can see on linux that port is Listening ) , but when i open "clint.html" page the method onopen never fire but server says

new client connected !
and after 2 minute it says

client disconnected
if i send message to client it will take 2 minutes then client will receive it, but it will disconnect again it seems to me that there is not stable connection between server and client. every time when i check websocket.readyState its not equal to 1
i disabled firewall and any security on vps server but still have this problem. i have to mention that normal php socket functions works without problem because i could test it and every thing works http://www.abrandao.com/2013/06/websockets-html5-php/ but about ratchet it seems it hang on onopen method.

  1. port 9091 is open
  2. firewall is disabled
  3. http:://www.abrandao.com/2013/06/websockets-html5-php/ works whiteout problem and can send and receive message from clients
  4. BUT Ratchet has problem onconnect

chat-server.php
`use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
require dirname(DIR) . '/vendor/autoload.php';

$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
9091
);
echo date("Y-m-d H:i:s")." chat-server Started on port 9091 \n";
$server->run();`

Chat.php class
`namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;

public function __construct() {
$this->clients = new \SplObjectStorage;
}

public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo date("Y-m-d H:i:s")." New connection! ({$conn->resourceId})\n";
$conn->send("Hello {$conn->resourceId} from server at : ".date("Y-m-d H:i:s"));
echo date("Y-m-d H:i:s")." Hello Sent to ({$conn->resourceId})\n";

}

public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf(date("Y-m-d H:i:s").'Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
$client->send($msg);
}
}
}

public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo date("Y-m-d H:i:s")." Connection {$conn->resourceId} has disconnected\n";
}

public function onError(ConnectionInterface $conn, \Exception $e) {
echo date("Y-m-d H:i:s")." An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}`

client.html :
`$(document).ready(function(){
connect();
});

var wsUri = "ws://myserverdomain.comOrIP:9091";

function connect() {
var ws = new WebSocket(wsUri);

ws.onopen = function() {
var now = new Date();
console.log(now + ' Connected to '+wsUri);
};

ws.onmessage = function(e) {
var now = new Date();
console.log(now + ' Message Recived From Server :', e.data);
};

ws.onclose = function(e) {
var now = new Date();
console.log(now +' Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
setTimeout(function() {
connect();
}, 1000)
};

ws.onerror = function(err) {
var now = new Date();
console.error(now + ' Socket encountered error: ', err.message, 'Closing socket')
console.error(err)
ws.close()
};
} `

Trying to listing on socket, works in some cases not in all

Hi, thanks for this project 😃.

I'm using this code from the README.md, with a small adjustment to output any data send to it.

    $loop = React\EventLoop\Factory::create();

    $socket = new React\Socket\Server($loop);
    $socket->on('connection', function ($conn) {
    echo "New connection " . $conn->getRemoteAddress() . "\n";


        $conn->on('data', function ($data) use ($conn) {
        echo "New msg from " . $conn->getRemoteAddress() . " msg: " . $data . "\n";
           $conn->close();
        });
    });
    $socket->listen(1337);

    $loop->run();

This works perfect if you start a netcat shell: nc localhost 6461, and type some data into it. However when I try to pipe some data to netcat e.g. echo "test" | nc localhost 6461, the connection is received (I see the new connection msg and ip address). However the data isn't received.

Is this normal behaviour or is this a bug? I'm trying to "catch" output from an existing service, which I can't change.

Thanks! (If you give me some hints where the bug is, I'll be happy to open a PR)

Http streaming client

Is it possible to write a http streaming client using React?

I have an application which connects to a server and the connection remains open and data is passed through that stream

something wrong

Fatal error: Uncaught exception 'InvalidArgumentException' with message 'First parameter must be a valid stream resource' in /Library/WebServer/Documents/www/comm/weixin/vendor/react/stream/src/Stream.php:40 Stack trace: #0 /Library/WebServer/Documents/www/comm/weixin/modules/chart/home.php(14): React\Stream\Stream->__construct('STDOUT', Object(React\EventLoop\StreamSelectLoop)) #1 [internal function]: modules\chart\home->index() #2 /Library/WebServer/Documents/www/comm/weixin/core/router.php(414): call_user_func_array(Array, Array) #3 /Library/WebServer/Documents/www/comm/weixin/core/router.php(391): router->load_route('modules\chart\h...', 'index', Array) #4 /Library/WebServer/Documents/www/comm/weixin/core/router.php(315): router->exec() #5 /Library/WebServer/Documents/www/comm/weixin/public/index.php(50): router::run() #6 {main} thrown

code id here

namespace modules\chart; use React\EventLoop\Factory; use React\Socket\Server; use React\Stream\Stream; class home{
public function index(){
	
	$loop = Factory::create();

	$client = stream_socket_client('tcp://127.0.0.1:1337');
	$conn = new  Stream($client, $loop);
	$conn->pipe(new Stream(STDOUT, $loop));
	$conn->write("Hello World!\n");

	$loop->run();


}
public function background(){
	$loop = Factory::create();

	$socket = new Server($loop);
	$socket->on('connection', function ($conn) {
	    $conn->write("Hello there!\n");
	    $conn->write("Welcome to this amazing server!\n");
	    $conn->write("Here's a tip: don't say anything.\n");

	    $conn->on('data', function ($data) use ($conn) {
	        $conn->close();
	    });
	});
	$socket->listen(1337);

	$loop->run();


}

}

Merge SocketClient component into this component

Here's the current situation:

  • This Socket component: Async, streaming plaintext TCP/IP and secure TLS socket server for ReactPHP
  • SocketClient component: Async, streaming plaintext TCP/IP and secure TLS socket client for ReactPHP

This is not exactly ideal, they share quite a bit of common code and actually have a dependency on one-another for their test suite.

Also, I believe this situation may be a bit confusing for consumers of this package. In particular our Datagram component provides both client and server side for datagram sockets (UDP).

As such, I'd vote for merging these two components into a single Socket component.

No data returned from server written to socket before connection close

Hi!

I have a following code

$socket->on('connection', function ($conn) 
{
  $conn->write("Hello there!\n");

  $conn->on('data', function ($data) use ($conn) {
    $conn->write("I have received a data!\n");
    $conn->close();
  });
});

The problem is I only receive "Hello there" string, but not "I have received a data!\n". I am not receiving second string even with sleep(5) or something before $conn->close() line. Is this a bug or I am doing something wrong?

Thank you in advance.

PS

comoser:

{
    "require": {
        "react/socket": "~0.4.0"
    }
}

php -v:

PHP 7.0.5 (cli) (built: Apr  2 2016 23:10:23) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

How to determine a message has been fully transfered

Hi,

I have created a server socket;

        $this->socket->on('connection', function(ConnectionInterface $connection){
               $connection->on('data', function($message) {
                   $this->createHandler($message, $connection)->handle($message);
               });
        });
        $this->socket->on('error', function($exception){
            $this->dispatcher->dispatch(new Event(EventStore::SOCKET_ERROR, $this, [
                'exception' => $exception
            ]));
        });
        $this->loop->run();

If a socket client send large chunks of data(greater than 65535) to the server. the listener for the event "data" will only get partial content every time.
How to gather all the partial content into a complete message?

[React/Socket/Server]: Can not create socket server #43

I'm using Fedora 26 with turned off selinux

When I try to create new instance of
new \React\Socket\Server( "127.0.0.1:5555", $loop);

[RuntimeException]
Failed to listen on "tcp://127.0.0.1:5555": Address already in use

$ sudo lsof -i tcp:5555
$

Test failures on Mac OS X

Not really an issue, more fyi:

There were 3 failures:

1) React\Tests\Socket\FunctionalSecureServerTest::testEmitsErrorIfConnectionIsCancelled
Expectation failed for method name is equal to <string:__invoke> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.

2) React\Tests\Socket\FunctionalTcpServerTest::testEmitsConnectionEvenIfConnectionIsCancelled
Expectation failed for method name is equal to <string:__invoke> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.

3) React\Tests\Socket\UnixConnectorTest::testValid
Failed asserting that Binary String: 0x756e69783a2f2f000000000000000000000000000000 is null.

/Users/andig/Documents/htdocs/react-socket/tests/UnixConnectorTest.php:62

No post data received

Hi,

I have a problem working with reactPHP (http server)

Scenario.

Apache receiving data
PHP script sending data via post to another server through a php script with curl to the reactphp server.
ReactPHP server sometimes receive data and sometimes not.

I have verified that from the apache server the data is always posted.

What is the problem then?

Thanks!

Please take a look at this simple code:

require 'vendor/autoload.php';

$loop   = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http   = new React\Http\Server($socket, $loop);

$http->on('request', function ($req, $res) {

print_r($req);


    $req->on('data', function($data) use ($req, $res) {

            parse_str($data,$datos);
            if(count($datos)==0)
            {

                    echo "No data \n";
            }


            $res->writeHead(200,
            array(
                    'Access-Control-Allow-Origin'=>'*',
                     'Content-Type' => 'text/plain'
             ));

            $res->end("Ok\n");
    });

});

$socket->listen(5000,10.1.45.39);
$loop->run();

Looks like there are too many opened sockets... Leak?

Ref: reactphp/http#27

Versions:

$ uname -a
Linux dev.qfox.ru 3.2.0-4-486 #1 Debian 3.2.51-1 i686 GNU/Linux
$ php -v
PHP 5.4.38-1~dotdeb.1 (cli) (built: Feb 19 2015 22:21:23)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with Xdebug v2.3.1, Copyright (c) 2002-2015, by Derick Rethans

I have a simple file app.php:

require 'vendor/autoload.php';

$app = function ($request, $response) {
    $response->writeHead(200, array('Content-Type' => 'text/plain'));
    $response->end("Hello World\n");
};

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);

$http->on('request', $app);
echo "Server running at http://0.0.0.0:1337\n";

$socket->listen(1337, '0.0.0.0');
$loop->run();

With installed react/http (here is my composer.json):

{
    "require": {
        "react/http": "0.3.*"
    }
}

Running it:

$ php app.php
Server running at http://127.0.0.1:1337

And sending 10k requests:

$ ab -n 10000 -c 500 http://localhost:1337/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
apr_socket_recv: Connection reset by peer (104)
Total of 9953 requests completed

Why some of requests was reseted by peer? Something is wrong?

$loop visibility prevent from extending Server

Hi,
in Server class
loop property is defined as private

Is there a specific reason for this?
Could it be protected?
Class can't be extended because of that...
Reason why one would extend: add context options or flags to stream_socket_server

Why is `$loop` private?

When creating a subclass of the socket server I am forced to override the constructor if I want to access the loop. What is the argument for making $loop private instead of protected?

Unix-style sockets - error 11, Resource temporarily unavailable

Hi guys,

If You have a moment pls look at this comment of mine. We tracked a possible issue with unix-style sockets (I merged ready pull request there). You will find there a small example to reproduce the issue.

The issue occurs when using unix socket with a lot of processes trying to connect in the same moment (starting 1 master instance and 100 slaves). Problem does not occur with TCP socket and TCPConnector.

Making $loop protected in Socket\Server and custom Connection classes?

The issue/scenario is that I would like to create a custom Connection and I am wondering what is the best way of doing it.

There are two possible ways that I can think of:

  • Allow extending Server by changing scope of $loop to protected.
  • Add a factory (like) connection class property in Server

Details for both approaches below, but first is there any reason for keeping $loop private in React\Socket\Server?

Approach 1 - changing scope of $loop to protected:
Changing scope to protected, then extending it via MyCustomServer in which I can override createConnection.

This approach is demonstrated below.

/** @event connection */
class Server extends EventEmitter implements ServerInterface
{
    public $master;
    protected $loop;    // changing scope from private to protected
    ....
}

/** MY Custom Server Class */
class MyCustomServer extends Server 
{
    public function createConnection($socket)
    {
        return new CustomConnection($socket, $this->loop);
    }
}

Approach 2 - Connection class property
Have a factory (sort of) way of creating a connection, in which a Server's property can be overwritten to create a connection e.g.

/** @event connection */
class Server extends EventEmitter implements ServerInterface
{
    public $master;
    private $loop;
    public $connectionClass = 'Connection';
    ....

    public function createConnection($socket)
    {
        return new $connectionClass($socket, $this->loop);
    }
}

Server::listen() is blocking if given a hostname

Migrated from reactphp/reactphp#181, originally reported 2013-04-13

Calling Socket\Server::listen($port, $host) with a hostname instead of an IPv4 address is a blocking operation.

Example:

$server = new Socket\Server($loop);
$server->listen(1234, 'example.com');

Giving a hostname will result in resolving it via DNS (blocking).

Server::createConnection breaks SRP

Shouldn't a ConnectionFactory be passed into Server::__construct instead of having a hardcoded classname in createConnection?
According to the single responsibility principle usage of an object should be separate from its construction right?

[Client] Connector does not honor /etc/resolv.conf

The Connector is currently hard-coded to default to Google's public DNS server 8.8.8.8. You can explicitly pass a custom DNS server (or Resolver instance) like this:

$connector = new Connector($loop, array(
    'dns' => '127.0.0.1'
));

Opening this ticket as a reminder - this actually depends on reactphp/dns#29

Clean up temporal dependence

The current socket API exhibits a temporal dependence:

$server = new Server($loop);
$server->listen(1234);
$server->getPort();
$server->on('connection', function () { });
$server->shutdown();
  • What happens if you call listen() twice?
    It's tempting to think that this will allow you to listen on two addresses – it does not.
  • What happens if you call shutdown() twice or before calling listen()?
    Errors out – should probably be ignored
  • What happens if you call getPort() before calling listen() or after calling shutdown()?
    Errors out – should probably be ignored
  • What happens if you call listen() after calling shutdown()?
    Should work, but makes for an awkward API.

Afaict most of this boils down to this:

  • What does a Server instance actually represent?
    Honestly, I'm not sure how to answer this. Once listen() has been called, it represents a "server socket", but until then?

Afaict most of these issues can be avoided if a Server instance always were to represent a "server socket" (which is possibly in a closed state). This means that the listen call would have to be part of the construction.

One possible API could look like this:

$server = $api->createServer(1234);
$server->getPort();
$server->on('connection', function() { });
$server->shutdown();

UDP Support

This is more of a question/discussion around UDP support to socket library.

My initial thinking as is to do the following:

  • Modify React\Socket\Server::__construct() as following
    public function __construct(LoopInterface $loop, $protocol = 'tcp')
    {
        $this->loop = $loop;
        $this->protocol = $protocol;
    }
  • Create TCP/UDP server based on $protocol in React\Socket\Server::listen() as following
        if ($this->protocol == 'tcp')
            $this->master = @stream_socket_server("tcp://$host:$port", $errno, $errstr);
        else
            $this->master = @stream_socket_server("udp://$host:$port", $errno, $errstr, STREAM_SERVER_BIND);
  • And then what? stream_socket_accept doesn't work with UDP so there is no $client (React\Socket\Connection) as such. One implementation can be to emit a udp event like so:
       // inside React\Socket\Server::listen()
       if ($this->protocol == 'tcp')
        {
            $this->loop->addReadStream($this->master, function ($master) {
                $newSocket = stream_socket_accept($master);
                if (false === $newSocket) {
                    $this->emit('error', array(new \RuntimeException('Error accepting new connection')));

                    return;
                }
                $this->handleConnection($newSocket);
            });
        }
        else
        {
            $this->loop->addReadStream($this->master, function($master)
            {
                $data = stream_socket_recvfrom($this->master, 1024, 0, $peer);
                $this->emit('udp', array($master, $data, $peer));
            });
        }
  • And then one can respond back to udp request like so:
    $socket = new React\Socket\Server($loop, 'udp');
    $socket->on('udp', function($socket, $data, $peer)
    {
        echo "$peer -> $data \n";
        stream_socket_sendto($socket, $data, 0, $peer);
    });

What are your thoughts on UDP support?

Strange unexpected behaviour

The following code outputs each request twice, any idea why? I think it might be a bug, but IDK if I am honest if I am doing something stupid

<?php

define( 'PORT', 3000 );
define( 'IP', '0.0.0.0' );

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

//Our HTTP Server
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server( $loop );
$http = new React\Http\Server( $socket );
$http->on(
        'request',
        function ( React\Http\Request $request,  React\Http\Response $response $

                echo "request rec'd '' {$request->remoteAddress}\n";
                $response->writeHead( 200, [ 'Content-Type' => 'text/plain' ] );
                $response->end( var_export( $request, true ) );

        }
);
$socket->listen( PORT, IP );
echo "Running on ".IP.":".PORT."...\n";
$loop->run();

Removed `full-drain` event from Buffer

Hello. I have a small problem after upgrade to latest version of reactphp/socket an event on buffer is missing. In previous version there was event full-drain. I use this event to fire handlers after data are completly sent to stream.

So is there some other way how to listen on simillar event? Right now i have patched actual buffer class React\Stream\Buffer:


    public function handleWrite()
    {
        $error = null;
        set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$error) {
            $error = array(
                'message' => $errstr,
                'number' => $errno,
                'file' => $errfile,
                'line' => $errline
            );
        });

        $sent = fwrite($this->stream, $this->data);

        restore_error_handler();

        // Only report errors if *nothing* could be sent.
        // Any hard (permanent) error will fail to send any data at all.
        // Sending excessive amounts of data will only flush *some* data and then
        // report a temporary error (EAGAIN) which we do not raise here in order
        // to keep the stream open for further tries to write.
        // Should this turn out to be a permanent error later, it will eventually
        // send *nothing* and we can detect this.
        if ($sent === 0 || $sent === false) {
            if ($error === null) {
                $error = new \RuntimeException('Send failed');
            } else {
                $error = new \ErrorException(
                    $error['message'],
                    0,
                    $error['number'],
                    $error['file'],
                    $error['line']
                );
            }

            $this->emit('error', array(new \RuntimeException('Unable to write to stream: ' . $error->getMessage(), 0, $error)));
            $this->close();

            return;
        }

        $exceeded = isset($this->data[$this->softLimit - 1]);
        $this->data = (string) substr($this->data, $sent);

        // buffer has been above limit and is now below limit
        if ($exceeded && !isset($this->data[$this->softLimit - 1])) {
            $this->emit('drain');
        }

        // buffer is now completely empty => stop trying to write
        if ($this->data === '') {
            // stop waiting for resource to be writable
            if ($this->listening) {
                $this->loop->removeWriteStream($this->stream);
                $this->listening = false;

                $this->emit('full-drain', array($this));
            }

            // buffer is end()ing and now completely empty => close buffer
            if (!$this->writable) {
                $this->close();
            }
        }
    }

added $this->emit('full-drain', array($this));

Async SSL/TLS server

Migrated from reactphp/reactphp#2, originally reported 2012-05-11

This ticket aims to serve as a basis for discussion whether (and how) we should provide an async SSL/TLS server.

SOCK_SEQPACKET support

To refactor a current project with a SOCK_SEQPACKET unix domain socket I was seeking to use reactphp. This seemed impossible because the stream_socket_* functions does not support this type of socket (but lower level socket_* functions do).

The issue I'm facing is the event loop is using stream_select, which is incompatible with the resources created by socket_create (which i need to use for a SOCK_SEQPACKET socket).

I would like to write a solution for this in reactphp but I need some thoughts on design considerations:

  • Should I need a SocketSelectLoop that runs alternating with the StreamSelectLoop? Is there a better way?
  • Should I be pulling on php developers to enable SOCK_SEQPACKET in stream_socket_* functions?
  • Even if php developers would implement this, would it be better to have a legacy implementation based on the low level socket_* functions?
  • Where will this new reactphp socket type's source code reside? In the reactphp/socket codebase, or a new module?

Thank you for any thoughts on this.

With kind regards,
Joffrey

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.