Im opening up a connection to a server that accepts XML requests. I am required to send two requests one after the other.
If I run the first request on its own I get data back
If I run the second request on its own I get data back
If I run both within a loop using the same connection, only the first request works, the second returns no data.
Is there something I need to send to the socket between each request to indecate the end of each request, otherwise what am I doing wrong?
// Open socket connection
$socket = pfsockopen($this->config['ip'], $this->config['port'], $errno, $errstr, 30);
// Try and open a connection
if ( ! $socket) {
throw new \Exception($errstr . '('.$errno.')');
}
// If connection was successfull start sending requests
else{
// Loop each request within the container
foreach($this->container as $key => $object){
print "Request" . ($key+1) . PHP_EOL;
// Reset data and post string
$data = array();
$xml_post_string = null;
// Create XML string
$xml = \LSS\Array2XML::createXML('request', $object->request);
$xml_post_string = $xml->saveXML();
// Add ending lines
$xml_post_string = $xml_post_string . PHP_EOL . PHP_EOL;
// Loop
fwrite($socket, $xml_post_string);
while ( ! feof($socket)) {
$data[] = fgets($socket, 1024);
}
// Tried adding, but fails
ftruncate($socket, 2);
if(count($data)){
print implode($data);
}
else{
print "No response from server - you broke it" . PHP_EOL;
}
}
}
fclose($socket);
A second attempt. The results are the same for any random server out there.
// Create a TCP/IP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// Connect the socket
socket_connect($socket, 'xxx.xxx.xxx.xxx', '80');
$xml_post_string_one = '<request><message>Hello first world</message></request>';
$xml_post_string_two = '<request><message>Hello second world</message></request>';
// FIRST ROUND //
// Send data to it
socket_write($socket, $xml_post_string_one, strlen($xml_post_string_one));
// Get data from it
socket_recv($socket, $bufA, 2048, MSG_WAITALL);
// Done
print strlen($bufA) . PHP_EOL; // Got info back
// SECOND ROUND //
// Send data to it
socket_write($socket, $xml_post_string_two, strlen($xml_post_string_two));
// Get data from it
socket_recv($socket, $bufB, 2048, MSG_WAITALL);
// Done
print strlen($bufB). PHP_EOL; // Returns 0, Why?
Related
This Is my code to connect java socket :-
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 12345);
while(true)
{
// read a line from the socket
$line = socket_read($socket, 1024, PHP_NORMAL_READ);
var_dump($line);
$someArray = json_decode($line, true);
$otp = $someArray["otp"];
if($someArray["msg"] == "otp_generation")
{
$myObj = new \stdClass();
$myObj->msg = "OTP RECEIVED NEED TO CONNECT";
$send = json_encode($myObj);
socket_send($socket, $send, strlen($send), 0);
}
exit;
}
My Question is -
When connection is established successfully server send one OTP to client and received successfully in client. Then i send data to server OTP RECEIVED acknowledgement, it also received in server. After OTP RECEIVED acknowledgement server send welcome msg to client. I cant get the welcome message. if i remove the "exit" code browser is still loading, finally crashing. Why i didn't receive the second data. anyone solve my issue. what i need to modify. am beginner for socket.
I need to display Welcome msg. What can i do?
You need to continue looping and read the next message, then break out of the loop.
while(true)
{
// read a line from the socket
$line = socket_read($socket, 1024, PHP_NORMAL_READ);
var_dump($line);
$someArray = json_decode($line, true);
if($someArray["msg"] == "otp_generation")
{
$otp = $someArray["otp"];
$myObj = new \stdClass();
$myObj->msg = "OTP RECEIVED NEED TO CONNECT";
$send = json_encode($myObj);
socket_send($socket, $send, strlen($send), 0);
} elseif ($someArray["msg"] == "welcome") {
// do whatever you need to do with the rest of the message
break; // then get out of the loop
} else {
echo "Unknown message received";
var_dump($someArray);
break;
}
}
I had to make a guess about how the welcome message is formatted, but this should give you the general idea.
Without new line cmd data is not send. This is the mistake i done. Finally i got the answer from my friend.
I just add the line below;-
socket_send($socket, $send."\r\n", strlen($send."\r\n"), 0);
Thanks #hemanth kumar and #Barmar
$ip="****"; //Set the TCP IP Address to connect too
$port="8088"; //Set the TCP PORT to connect too
$command="hi"; //Command to run
$req['path'] = $path;
$post = json_encode($req);
//Connect to Server
$socket = stream_socket_client("tcp://{$ip}:{$port}", $errno, $errstr, 30);
if($socket) {
//Start SSL
stream_set_blocking ($socket, true);
stream_socket_enable_crypto ($socket, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT);
stream_set_blocking ($socket, false);
//Send a command
fwrite($socket, $post);
$buf = null;
//Receive response from server. Loop until the response is finished
while (!feof($socket)) {
$buf .= fread($socket, 20240);
}
//close connection
fclose($socket);
echo "<pre>";
print_r($buf); exit;
//echo our command response
return json_decode($buf);
}
This is my code.
this code is working fine for below 8192 bytes value. but
it can't get the above 8192 bytes what i need to get above this bytes.
because i need get the more bytes of data here
Please provide one example
Thanks in advance
When you write to a network stream, a single call to fwrite() does not necessary writes the whole data.
There is a note at http://php.net/manual/en/function.fwrite.php which says:
Writing to a network stream may end before the whole string is
written. Return value of fwrite() may be checked:
<?php
function fwrite_stream($fp, $string) {
for ($written = 0; $written < strlen($string); $written += $fwrite) {
$fwrite = fwrite($fp, substr($string, $written));
if ($fwrite === false) {
return $written;
}
}
return $written;
}
?>
You may wonder, where does this 8192 number come from.
It seems like this is the default chunk size for the stream.
You can check and change chunk size via stream_set_chunk_size() function
You have set the socket in non-blocking mode:
stream_set_blocking ($socket, false);
In non-blocking mode, you should wait for data availability on the socket before trying to perform read operations. PHP provides stream_select function for this purpose.
So you should whether make the socket blocking, or handle events with stream_select.
The port is 5792 and the ip is 123.123.123.123. I am able to send data to the ip, like so:
$host = "tcp://123.123.123.123";
$port = 5792;
$errstr = '';
$errno = '';
$fp = fsockopen($host, $port ,$errno, $errstr, 30);
if (!$fp) {
print 'COULD NOT CONNECT! <br />';
echo "$errstr ($errno)<br />\n";
die();
}
else {
print 'SUCCESS!<br />'
}
The sending seems to also work:
$message = 'hello';
fputs ($fp, $message );
The problem comes in when receiving data:
print fread($fp, 128);
This prints:
hello
... to the screen! So in other words, it's echoing what I'm sending it. Now, I know all messages are encapsulated within an XML element. Within this element a service request can be placed, which is also encapsulated in a XML element.
The encapsulated XML element is called "ROOT" and within this I can place the service request request. Let's call the actual service request I'm trying to accomplish "topUp".
Assuming there is a root xml element called ROOT, which encapsulates the service request "topUp", what would be the standard way to submit this XML as a string?
Is it normal to expect a server to echo your request whenever it can't understand what you are saying?
It is vital that u know the XML structure of the request command. In any case you can send you command in such a way too
$message = "<root>"."\n";
$message .= "<request>topUp</request>"."\n";
$message .= "</root>"."\n";
fputs ($fp, $message );
But unless you send your request structure defined you might not get the result you want.
We're using a system at the moment that takes an incoming JSON request over TCP and responds using JSON too. Currently I've set up my socket like so in PHP:
$socket = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$socket)
{
fwrite($socket, $jsonLoginRequest); // Authentication JSON
while(json_decode($loginResponse) == false) // We know we have all packets when it's valid JSON.
{
$loginResponse .= fgets($socket, 128);
}
// We are now logged in.
// Now call a test method request
fwrite($socket, $jsonMethodRequest);
while(json_decode($methodResponse) == false) // We know we have all packets when it's valid JSON.
{
$methodResponse .= fgets($socket, 128);
echo $methodResponse; // print response out
}
// Now we have the response to our method request.
fclose($socket);
}
else
{
// error with socket
}
This works at the moment, and the server responds to the method request. However, some methods will respond like this to acknowledge the call, but will also respond later on with the results I'm after. So what I really need is a TCP listener. Could anyone advise how I could write a TCP listener using fsock like I have above?
Thanks
To create a listening socket use the following functions:
socket_create_listen (this one is cool)
socket_accept
I'm not shure if fwrite()/fread() are working with those sockets otherwise you have to use the following functions:
socket_recv
socket_send
Message-loop
I have now written some function to read a single JSON responses with the assumption that multiple responses are separated by CRLF.
Here's how I would do it (assuming your php-script has unlimited execution time):
// ... your code ...
function readJson($socket) {
$readData = true;
$jsonString = '';
while(true) {
$chunk = fgets($socket, 2048);
$jsonString .= $chunk;
if(($json = json_decode($jsonString)) !== false) {
return $json;
} elseif(empty($chunk)) {
// eof
return false;
}
}
}
// ....
// Now call a test method request
fwrite($socket, $jsonMethodRequest);
$execMessageLoop = true;
while($execMessageLoop) {
$response = readJson($socket);
if($response === false) {
$execMessageLoop = false;
} else {
handleMessage($socket, $response);
}
}
function handleMessage($socket, $response) {
// do what you have to do
}
Now you could implement the "handleMessage" function which analyses the response and acts to it.
I'm trying to set up a socket server in php that stays open. This example taken from php.net will close after it receives connection...even after I comment out socket_close($spawn)
<?
// set some variables
$host = "192.168.1.109";
$port = 1234;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create
socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port) or die("Could not bind to
socket\n");
// start listening for connections
$result = socket_listen($socket, 3) or die("Could not set up socket
listener\n");
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket) or die("Could not accept incoming
connection\n");
// read client input
$input = socket_read($spawn, 1024) or die("Could not read input\n");
// clean up input string
$input = trim($input);
// reverse client input and send back
//$output = $input . "\n";
$output = strrev($input) . "\n";
echo $input;
socket_write($spawn, $output, strlen ($output)) or die("Could not write
output\n");
// close sockets
//socket_close($spawn);
//socket_close($socket);
?>
and here is the code for the client connecting...
<?php
$fp = fsockopen("192.168.1.109", 1234, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
//$out = "testing";
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: 127.0.0.1\r\n";
$out .= "Connection: Close\r\n\r\n";
$out .= "testing\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
//exit();
}
//exit;
?>
socket_read without the O_NONBLOCK flag (see socket_set_nonblock) is a blocking operation, so it will wait there until it receives something.
As soon as something is received, the rest of the script continues, and exits, as there is no loop in place to do the next read. (i.e: in a server it's usual to do a while(true){} loop)
You need to wrap the accept in a loop or something. It closes because the script execution has ended.
You could do something like this:
while ($spawn = socket_accept($socket)) {
//do stuff
}