From: Ryan Sun on
Stream and networking programming seems like a rock on the way to
ZCE for most people, so I'm learning some socket examples before I sit
in the room for exam.
Here is the script for server

<?php
$socket = stream_socket_server("tcp://127.0.0.1:1037", $errno, $errstr);
if(!$socket)
{
echo "$errstr ($errno) \n";
}
else
{
while($conn = stream_socket_accept($socket))
{
echo "New connection \n";
fwrite($conn, "Hello World \n");
fwrite($conn, "Do you want to close server? Yes(Y)/No(N) \n");
if(!feof($conn))
{
$answer = fread($conn, 1);
if($answer == 'Y')
{
echo "User choose to close server. \n";
break;
}
elseif($answer == 'N')
{
echo "Service continue... \n";
}
else
{
echo "Unknown answer '$answer'. \n";
}
}
fclose($conn);
}
fclose($socket);
}

and the client

<?php
$socket = stream_socket_client('tcp://127.0.0.1:1037', $errno, $errstr);
if(!$socket)
{
echo "$errstr ($errno) \n";
}
else
{
$answer = "Y";// fgets(STDIN)
fwrite($socket, $answer);
while(!feof($socket))
{
echo fread($socket, 100);
}
}

everything works, but if I write after read in client

<?php
$socket = stream_socket_client('tcp://127.0.0.1:1037', $errno, $errstr);
if(!$socket)
{
echo "$errstr ($errno) \n";
}
else
{
while(!feof($socket))
{
echo fread($socket, 100);
}
$answer = "Y";// fgets(STDIN)
fwrite($socket, $answer);
}

server&client hangs after output and time out later.

Can any1 point out whats the reason and the more correct way to get
socket client input in socket server?
From: "Bob McConnell" on
From: Ryan Sun

> Stream and networking programming seems like a rock on the way to
> ZCE for most people, so I'm learning some socket examples before I sit
> in the room for exam.
> Here is the script for server

<snip>

> server&client hangs after output and time out later.
>
> Can any1 point out whats the reason and the more correct way to get
> socket client input in socket server?

I have not done any socket programs in PHP, but I have in Assembler, C
and Perl. First, I don't think feof() will do what you think it does. I
wouldn't expect it to show up until after the other end has actually
closed the connection.

The other problem has to do with thinking an fread() will always give
you everything you sent in an fwrite(). TCP is a stream protocol, there
are no guarantees about delivering a complete message in one read, or
that two writes won't be read together. It only guarantees that all
octets will eventually be delivered in the same order they were sent, or
you will get an error. The buffering is completely hidden and outside of
your control. If you want writes to be atomic, you want UDP, but then
you lose the guarantee of delivery. If you want to enforce a structure
on the data in that stream, it is your application's responsibility to
reconstruct that data at the receiver.

One other detail that may or may not make a difference. TCP actually
defines two independent pipes, one in each direction. Many Unix
applications create two processes to service a socket, one to send, the
other to receive. Only occasionally does a protocol require alternating
messages similar to a conversation or ping-pong match.

Bob McConnell
From: Ryan Sun on
Thanks for your reply

> First, I don't think feof() will do what you think it does. I
> wouldn't expect it to show up until after the other end has actually
> closed the connection.

I found unread_bytes in stream_get_meta_data should be more reliable

> TCP is a stream protocol, there
> are no guarantees about delivering a complete message in one read, or
> that two writes won't be read together. It only guarantees that all
> octets will eventually be delivered in the same order they were sent, or
> you will get an error.

thanks 4 pointing out the difference between tcp and udp, I had learnt a lot ^^

>The other problem has to do with thinking an fread() will always give
>you everything you sent in an fwrite()
Interestingly, I use 'telnet 127.0.0.1 1037' for testing later(on
windows) and everything works, the php server got the input from
telnet client, so I assume there is something wrong in the php client,
the fwrite statement...
From: "Bob McConnell" on
From: Ryan Sun

> Thanks for your reply

You are welcome.

>> The other problem has to do with thinking an fread() will always give
>> you everything you sent in an fwrite()

> Interestingly, I use 'telnet 127.0.0.1 1037' for testing later(on
> windows) and everything works, the php server got the input from
> telnet client, so I assume there is something wrong in the php client,
> the fwrite statement...

What are the actual symptoms? Are you sure both ends are using the same
character encoding?

TCP transports a series of octets, or bytes. Again it is up to the
applications on both ends of the stream to agree on interpretation of
those octets, either separately or in sequence. For example, if integers
or floats are sent in a native format, but one end is little Endean
while the other is big Endean, there will be some differences in what
the two ends read from that stream. Likewise, if one end is expecting
ASCII, while the other is sending UTF-8, there may be the occasional
multi-byte value that gets scrambled.

On the other hand, I may be way out in left field.

Bob McConnell