7

I would like to ask how to create a PHP socket which able receive request from android phone in real time? For now, i done this part of code and able test it using telnet. However, when the android phone try to connect, it unable receive or send anything to server.

if (!defined('SOCKET_ADDRESS')) {
    define('SOCKET_ADDRESS', '192.168.1.4');
}

if (!defined('SOCKET_PORT')) {
    define('SOCKET_PORT', '5888');
}

if (!defined('MAX_CLIENTS')) {
    define('MAX_CLIENTS', '10');
}
set_time_limit(0);

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, SOCKET_ADDRESS, SOCKET_PORT) or die('Could not bind to address ' . SOCKET_ADDRESS . ' on port ' . SOCKET_PORT . "!\n");
socket_listen($socket, MAX_CLIENTS) or die("Could not setup socket listener!\n");

// setup read socket array
$read = array();

// client array w/ default initial socket
$clients = array('0' => array('socket' => $socket));

// force debug at first run..
$debug = true;
$time = time();
printf('Time: %d%s', $time, "\n");
$status = true;
while ($status) {

    if (time() - $time >= 10) {
        $time = time();
        printf('Time: %d%s', $time, "\n");
        $debug = true;
    }
    if ($debug === true) {
        printf('Debug: %s%s', $debug, "\n");
    }
    // $read[0] = $socket;
    if ($debug) {
        var_dump($read);
    }

    // Handle clients
    for ($i = 0; $i < count($clients); $i++) {
        if (isset($clients[$i]['socket'])) {
            if ($debug === true) {
                printf('Setting socket %d to client %d%s', $i, $i, "\n");
            }
            $read[$i] = $clients[$i]['socket'];
        }
    }
    if ($debug) {
        var_dump($read);
    }
    // Any changed sockets?
    // $write and $except are only placeholders
    $changed_sockets = socket_select($read, $write = NULL, $except = NULL, 0);
    if ($debug === true) {
        printf('Changed sockets: %d%s', $changed_sockets, "\n");
    }
    // Handle new connections
    if (in_array($socket, $read)) {
        for ($i = 0; $i < MAX_CLIENTS; $i++) {
            if (!isset($clients[$i])) {
                $clients[$i]['socket'] = socket_accept($socket);
                socket_getpeername($clients[$i]['socket'], $ip);
                $clients[$i]['ip'] = $ip;
                printf('Accepting connection into client %d from %s%s', $i, $ip, "\n");
                break;
            }
            // } elseif($i == MAX_CLIENTS - 1) {
            // echo 'Too many clients connected!', "\n";
            // }
            if ($changed_sockets < 1) {
                continue;
            }
        }
    }
    if ($debug) {
        var_dump($clients);
    }

    for ($i = 0; $i < count($clients); $i++) {
        $client = $clients[$i];
        // Has our client socket seen any changes?
        if (in_array($client['socket'], $read)) {
            printf('Client %d has changed! Reading...%s', $i, "\n");
            $data = socket_read($client['socket'], 1024);
            if ($data === false) {
                $error = socket_strerror(socket_last_error());
                printf('An error occured...%s%s', $error, "\n");
            }
            printf("Read raw data %s from client %i%s", $data, $i, "\n");
            if ($data === null) {
                // disconnected
                unset($clients[$i]);
            }

            $data = trim($data);
            if ($data == 'Q') {
                printf('Received exit command from client%s', "\n");
                socket_close($clients[$i]['socket']);
                $status = false;
            } elseif ($data) {
                // Strip whitespace
                printf('Received data: %s from client %d%s', $data, $i, "\n");
                $output = sprintf('%s%s%s', $data, "\n", chr(0));
                socket_write($client['socket'], $output);
            }
        }
    }

    // reset debug
    $debug = false;
}

socket_close($socket);

2 Answers 2

4

If you want to skip what I’ve written, here’s a download to a fully working PHP socket server and Android socket client (with all the source code): https://developersfound.com/PHP_SocketServer_Android_SocketClient.zip

Or for information that you may find useful read on ....

An important rule of thumb here is to understand the differences between the ‘HTTP request/response model’ and the TCP model. The advantage of TCP over HTTP is that you can queue messages and take advantage of full duplex (two way simultaneous communication), also open TCP connections are a bit more responsive. Unless your solution absolutely needs queuing and or benefits from full duplex you should actually be using RPC over HTTP or REST. HTTP is much easier to implement and more reliable on mobile devices. Moving long distances on mobile devices, tends to break TCP connections and when the connection is broken you lose any queuing and have to reconnect. Reconnecting also takes up a lot more battery power and can hang the client system. Another disadvantage is that a live system can end up with a lot of live connections and slow your servers quite significantly; more so than a busy HTTP server.

However if your solution needs, or benefits from the advantages of TCP, read on ....

This code base (in the link above) has a fully functional (self contained) PHP server and a fully functional Android socket client. This code base should provide a strong reference for implementing client sockets in Android. This code base is implemented in accordance with Android best practices as well as serving as a strong reference for implementing long running process for stability.

It is noteworthy to understand that the Android docs recommend using Services to implement sockets because sockets cannot be parsed. For this reason a singleton type model is necessary. You will notice that this codebase uses AIDL to communicate with the service and broadcasts to update the UI. This is best practice as sockets must be protected from garbage collection and activity recreation, which would normally break the socket connections. Services bound through the AIDL and Thread Executors are all associated with best practices for the stability of long running processes.

Hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

How to change your source, to make client listening all the time without need to sent response (message) to the server. I made some changes on server to write messages when db is updated. When I write messages to client, I need to press button(who send outbound message) and then I receive last sent message. It is like messages stuck somewhere (in buffer or...) I don't understand java very well :(
I haven't looked into this properly yet but try experimenting with this post on php.net: php.net/manual/en/function.flush.php. You should be able to combine this code with a character flag in the transmission to signal the end of the socket process. If this works let me know. Otherwise I'll spend some of my spare time solving this problem.
Hello there, the link is currently dead. Did you move the code? Kindly provide the new location.
3

Add this library in build.gradle.

   compile "org.java-websocket:Java-WebSocket:1.3.0"

to connect:

 private void connectWebSocket() {
    URI uri;
    try {
        uri = new URI("ws://websockethost:8080");
    } catch (URISyntaxException e) {
        e.printStackTrace();
        return;
    }

    mWebSocketClient = new WebSocketClient(uri) {
        @Override
        public void onOpen(ServerHandshake serverHandshake) {
            Log.i("Websocket", "Opened");
            mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL);
        }

        @Override
        public void onMessage(String s) {
            final String message = s;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    TextView textView = (TextView)findViewById(R.id.messages);
                    textView.setText(textView.getText() + "\n" + message);
                }
            });
        }

        @Override
        public void onClose(int i, String s, boolean b) {
            Log.i("Websocket", "Closed " + s);
        }

        @Override
        public void onError(Exception e) {
            Log.i("Websocket", "Error " + e.getMessage());
        }
    };
    mWebSocketClient.connect();
}

to send message:

public void sendMessage(String message) {
    mWebSocketClient.send(message);
}

ref:https://github.com/elabs/mobile-websocket-example

2 Comments

Can i send an xml file using android to php?
Yes you can send as string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.