Hot questions for Using Transmission Control Protocol in php

Question:

I am trying to send data from PHP TCP server to JAVA TCP client. I am comparing my results by comparing hex values of the data.

PHP script reads STDIN, sends it through socket one byte at a time and java reads it using DataInputStream.read(), converts to hex and displays.

If I manually type data into script - it works ok. If I use file with data - it works OK But when I assign /dev/urandom(even few bytes) - the data on the java side is coming corrupted. There is always a hex of value efbfbd in random places instead of correct data. Please help me with this issue. PHP code:

$f = fopen( 'php://stdin', 'rb' );
while($line = fread($f, 1)){

    $length = 1;
    echo bin2hex($line)."\n";
    echo socket_write($client, $line, 1)."\n";

     $sent = socket_write($client, $line, $length);

if ($sent === false) {

    break;
}

// Check if the entire message has been sented
if ($sent < $length) {

    // If not sent the entire message.
    // Get the part of the message that has not yet been sented as message
    $line = substr($line, $sent);

    // Get the length of the not sented part
    $length -= $sent;

}

Java code:

in = new DataInputStream(clientSocket.getInputStream());

            byte[] data = new byte[1];

            int count = 0;
            while(in.available() > 0){
                //System.out.println(in.available());
                     in.read(data);
                String message = new String(data);

                System.out.println(message);
                //System.out.flush();

                System.out.println( toHex(message) );
                //in.flush();
                message = "";



            }

Answer:

You're stumbling upon encoding. By calling new String(data) the byte array is converted using your default encoding to a string, whatever this encoding may is (you can set the encoding by java -Dfile.encoding=UTF-8 to UTF-8 for example).

The Java code you want would most likely look the following:

    in = new DataInputStream(clientSocket.getInputStream());

    byte[] data = new byte[1];

    int count = 0;
    while (in.available() > 0) {
        // System.out.println(in.available());
        in.read(data);
        String hexMessage = Integer.toHexString(data[0] & 0xFF);
        String stringMessage = new String(data, "UTF-8"); // US-ASCII, ISO-8859-1, ...
        System.out.println(hexMessage);
    }

Update: I missed the 32bit issue. The 8-bit byte, which is signed in Java, is sign-extended to a 32-bit int. To effectively undo this sign extension, one can mask the byte with 0xFF.

Question:

My Design

I'm using sockets to implement a chat server.

The client side uses Java's java.net.Socket and BufferedReader to read messages from the server.

The server side uses Php's socket_read() to get messages from the clients.

And it uses Php's socket_write() to send messages from the server. socket_write() does not guarantee that the entire original message will be written out, which means I may have to make multiple calls to it to send out the entire original message.

(In terms of design, clients send messages to the server, and server reroutes those messages to the appropriate clients.)

Concerns

My concerns are that a message may be broken up into several smaller messages. So when the server or a client reads an incoming message, it may actually be a fragment of the original.

Questions

Is this something I need to account for? If yes, how?

Possible Solution

Right now I'm thinking about using byte stuffing (which is a networking technique to insert bytes into the original message that serve as flags to mark the start and end of a message before sending it out).


Answer:

If you need application-level messages, then you have to implement them at application level. There are several common approaches:

1) Use fixed-length messages.

2) Prefix each message with its length.

3) Use an 'end of message' marker that naturally never appears in your messages.

4) Use an 'end of message' marker and escape it if it appears in your messages.

Question:

Okay, so I have an apache server that has text/data that I want to sendoff to a Java client. The issue is that the data will change often, and I don't want the client to constantly do a read on the server, because obviously I don't want a constant ping. I know that I can make a client socket but that requires my users to port forward to access the server, which isn't going to work for my users.

What I've found online is UDP punching may work or NAT Transfer, but I cant find any examples for how to do it in Java.

  • If you have any questions please feel free to comment :)

Answer:

You could Recieve Server-Sent Event notifications, in which the server send the data, using PHP and JS as an example:

var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
};

PHP:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>