Comments (6)
@Tick007 Welcome to @reactphp! 👋
I agree ReactPHP can be confusing when you're starting out first, so let's simplify your example a bit:
$conn->write($frame);
$conn->on('data', function ($data) {
$cpr = new ContProtocol;
$cpr->readMessage($data);
});
$conn->on('data', function ($data) {
$cpr = new ContProtocol;
$cpr->readMessage($data);
});
This will send a single message ($frame
) and will wait for the data twice. This means that every time your connection receives some data, both data
handlers will be invoked with the same data from the stream.
The way I understand your problem, you only want to attach a single data
handler. Then, parse this as a continuous stream with some delimiter between individual messages. For instance, you can use a newline delimiter between message so each single line can be read as a JSON structure with https://github.com/clue/reactphp-ndjson.
The same logic also applies to binary protocols (look up message framing for more details). If you can tell us more about the protocol you're using, we might be able to help you.
Additionally, the time_nanosleep()
function must not be used in a truly non-blocking application. I suppose this was only left here for testing purposes, but keep in mind that this will block your entire loop. It looks like this can be removed, but if you want to "wait", use the $loop->addTimer()
method instead.
I'll assume this is resolved and will close this for now, please feel free to report back otherwise 👍
from reactphp.
Hello clue, thank you for your answer.
Doesn't $loop2->stop();
should stop wait for new data receiving on open socket connection ?
So my goal was to make analog of following code:
$pop_conn = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); socket_connect ( $pop_conn , $dstip, $dstport ); foreach ($arr as $num => $frame) { socket_write($pop_conn, $frame ); time_nanosleep(0, 001000000); $data = socket_read ($pop_conn, 4048); $cpr = new ContProtocol; $cpr->readMessage($data); $cps[$cpr->hdr['UnitNum'][2]] = $cpr; } socket_close ($pop_conn);
ContProtocol, that I use - is some binary protocol, is not JSON. It has it own HEADER and END, and it is not very comfortable to separate single frame from common stream. Much easer to receive individual messages with single frame. Code above do that job. My project is some simulator, where one part receives binary data, repack it to json (with nessesary aditions) and sends to websocket. Websoket works fine, thanks, but another part is expiriences some trouble :)
from reactphp.
@Tick007 I understand where you're coming from. The problem with streaming protocols is this: If you send "hello" and "world" as two "messages", there's no guarantee the receives sees these exact message boundaries, it may as well receive "helloworld" as a single message or "h" and "elloworld" or any combination thereof. That's why you need to employ message framing to avoid this situation.
This is nothing specific to this project, but how the underlying transport mechanisms work (for good reason).
You can also introduce a small delay between each message, which makes it more likely you'll receive each message after another, but depending on your load and/or message size, it's not something you can rely on and you're back to square one. Even if it does work, it's effectively limiting your throughput and increasing latency.
If your protocol is strictly following request/response semantics and you don't want to take advantage of pipelining (sending multiple request messages at once without having to wait for the first response), you may also design this to be strictly sequential. In this case, you can send a single request message, wait for the response and only then send the next request message. This guarantees you're receiving full messages between each step, but you're missing out on the huge I/O improvements pipelining can give you 👍
from reactphp.
Looks like i got you:
` $loop2 = React\EventLoop\Factory::create();
$connector2 = new React\Socket\Connector($loop2);
$cps=null;
echo '100 request'."\n\r";
$connector2->connect($dstip . ':' . $dstport)->then(
function (React\Socket\ConnectionInterface $conn) use ($loop2, &$arr, &$cps) {
$conn->on('data', function ($data) use ($conn, $loop2, &$cps) {
$cpr = new ContProtocol;
$cpr->readMessage($data);
$cps[$cpr->hdr['UnitNum'][2]] = $cpr;
//echo mb_strlen($data);
//echo "\n\r";
}, function (Exception $exception) use ($loop2) {
echo "Cannot data connect to server: " . $exception->getMessage();
$loop2->stop();
});
foreach ($arr as $num => $frame) {
$loop2->addTimer(0.1, function () use ($conn, $frame) {
$conn->write($frame);
});
}
$loop2->addTimer(1, function () use ($loop2) {
$loop2->stop();
});
});
$loop2->run();`
Works way faster than socket_creatr etc...
Thank you.
from reactphp.
May be you should add this to docs....
from reactphp.
Happy to hear you're making some progress!
foreach ($arr as $num => $frame) {
$loop2->addTimer(0.1, function () use ($conn, $frame) {
$conn->write($frame);
});
}
Note that this piece of code will probably not work the way you may expect it to work. Assuming you have 100 entries in your array, it will start 100 timers which all trigger at around the same time in 100ms. This means a single timer would pretty much do the same thing. I would even question if this timer is needed at all (depends on your use case of course)?
Additionally, as per https://github.com/reactphp/event-loop#addtimer there is no guarantee that timers that are scheduled to trigger at the same time will actually execute in order. This means the writing the second chunk might as well happen before writing the first chunk from your array (which may or may not be a problem for your use case).
If you're sure you need timers in here (which I would question), I would suggest scheduling each timer with an interval of 0.1 * $num
so that the array position is taken into account (assuming its a vector/list here).
$conn->on('data', function ($data) use ($conn, $loop2, &$cps) {
// …
}, function (Exception $exception) use ($loop2) {
echo "Cannot data connect to server: " . $exception->getMessage();
$loop2->stop();
});
Note that as per https://github.com/reactphp/stream#data-event, this event handler only accepts a single function. The second function has no effect. It looks like this is supposed to handle failed connections attempts, so this should be added as a second function to the connection promise instead 👍
May be you should add this to docs....
We're happy to accept PRs if you feel there's anything that we can improve in our documentation!
from reactphp.
Related Issues (20)
- Why it's named reactphp? HOT 7
- Discussion about the communication channel HOT 18
- Outdated blog posts HOT 5
- Letsencrypt + SSL version or cipher mismatch HOT 14
- Uncaught RuntimeException: Failed to listen on reactphp HOT 5
- multipart video streaming & only send 1 min of the video HOT 2
- Documentation is out of date HOT 2
- Connect reactphp App to cPanel HOT 5
- 5454
- Is the project still live? HOT 2
- State-Management Error - Memory leak HOT 5
- Rename `master` branches for ReactPHP projects HOT 4
- http server return "Error: socket hang up" HOT 1
- Enable GitHub Discussions for ReactPHP repositories HOT 4
- Does ReactPHP 1.3 work with ZMQ? HOT 1
- Compatibility Issues HOT 1
- Execution Error
- exit() hangs when called after getSocket(ZMQ::SOCKET_PULL) but NOT after getSocket(ZMQ::SOCKET_PUSH)
- PHP Fatal error: Uncaught Error: Class "React\Http\HttpServer" not found HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from reactphp.