PHP сокет с Android


Я хотел бы спросить, как создать PHP-сокет, способный получать запросы с телефона Android в режиме реального времени? На данный момент я выполнил эту часть кода и смог протестировать ее с помощью telnet. Однако, когда телефон Android пытается подключиться, он не может принимать или отправлять что-либо на сервер.

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);
Author: Matthew Chin, 2015-03-20

2 answers

Добавьте эту библиотеку в build.gradle.

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

Для подключения:

 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();
}

Для отправки сообщения:

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

Ссылка: https://github.com/elabs/mobile-websocket-example

 2
Author: Selim YILDIZ, 2015-03-20 04:31:13

Если вы хотите пропустить то, что я написал, вот загрузка полностью работающего сервера сокетов PHP и клиента сокетов Android (со всем исходным кодом): http://developersfound.com/PHP_SocketServer_Android_SocketClient.zip

Или для получения информации, которая может оказаться полезной, читайте дальше....

Важным эмпирическим правилом здесь является понимание различий между "моделью запроса/ответа HTTP" и моделью TCP. Преимущество TCP по сравнению с HTTP заключается в том, что вы можете стоять в очереди сообщения и использовать преимущества полного дуплекса (двусторонняя одновременная связь), также открытые TCP-соединения немного более отзывчивы. Если только ваше решение абсолютно не нуждается в очередях и не извлекает выгоду из полного дуплекса, вам следует использовать RPC через HTTP или REST. HTTP намного проще в реализации и надежнее на мобильных устройствах. Перемещение на большие расстояния на мобильных устройствах, как правило, приводит к разрыву TCP-соединений, и когда соединение прерывается, вы теряете очередь и должны повторно подключиться. Повторное подключение также потребляет намного больше энергии аккумулятора и может зависнуть клиентская система. Еще одним недостатком является то, что действующая система может в конечном итоге иметь много активных подключений и значительно замедлять работу ваших серверов; в большей степени, чем загруженный HTTP-сервер.

Однако, если ваше решение нуждается в преимуществах TCP или извлекает из них выгоду, читайте дальше....

Эта кодовая база (по ссылке выше) имеет полностью функциональный (автономный) PHP-сервер и полнофункциональный клиент сокетов для Android. Эта кодовая база должна предоставьте надежную ссылку для реализации клиентских сокетов в Android. Эта кодовая база реализована в соответствии с лучшими практиками Android, а также служит надежным ориентиром для реализации длительного процесса для обеспечения стабильности.

Следует понимать, что документы Android рекомендуют использовать службы для реализации сокетов, поскольку сокеты не могут быть проанализированы. По этой причине необходима модель одноэлементного типа. Вы заметите, что эта кодовая база использует AIDL для связи с служба и трансляции для обновления пользовательского интерфейса. Это лучшая практика, так как сокеты должны быть защищены от сбора мусора и активного отдыха, которые обычно нарушают соединения сокетов. Службы, связанные с помощью AIDL и исполнителей потоков, связаны с передовыми методами обеспечения стабильности длительных процессов.

Надеюсь, это поможет.

 1
Author: user2288580, 2017-08-24 02:00:27