2011-02-04 25 views
7

Quindi, ho mIRC che fa un ascolto (portami con me su questo) sulla porta 1235 e ho provato a fare uno script php per collegarmi a tale porta sul mio server localhost.PHP Socket è mezzo lavoro

Il mio localhost è un Apache + PHP pulito con mIRC eseguito su un altro computer (all'interno della lan).

Lo script funziona a metà destra come: 1) si connette alla porta 1235 2) invia il $ i 2.1), ma dall'altra parte non msg è ricevuto (aka ottengo un calzino leggere evento, ma nessun testo si apre) 3) si legge tutti i messaggi in arrivo correclty 4) si chiude quando 'fine' è il messaggio drumroll 5) funziona solo se la funzione, mentre non è presente. 5.1) alias Inifi-loading. mostra solo eco quando socket viene chiuso tramite 'finale'

ecco il codice, che è un semplice esempio ho trovato su php.net, grazie in anticipo :)

<?php 
//The Client 
error_reporting(E_ALL); 

$address = "192.168.1.101"; 
$port = 1235; 

/* Create a TCP/IP socket. */ 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
if ($socket === false) { 
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; 
} else { 
    echo "socket successfully created.\n"; 
} 

echo "Attempting to connect to '$address' on port '$port'..."; 
$result = socket_connect($socket, $address, $port); 
if ($result === false) { 
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n"; 
} else { 
    echo "successfully connected to $address.\n<br>"; 
} 
$allow = true; 
$i = 0; 
while ($allow == true) 
{ 
    $i++; 
    echo "Sending $i to server.\n<br>"; 
    socket_write($socket, $i, strlen($i)); 

    $input = socket_read($socket, 2048); 
    if ($input == 'end') { 
     $allow = false; 
    } 
    echo "Response from server is: $input\n"; 
    sleep(5); 
} 

echo "Closing socket..."; 
socket_close($socket); 
?> 

questo è ciò che ottengo nel browser, dopo aver detto 'end'

socket creato correttamente. Tentativo di connessione a '192.168.1.101' sulla porta '1235' ... connesso correttamente a 192.168.1.101. Invio 1 al server. Risposta dal server è: ok risposta dal server è: fine

questo è in mIRC:

prova: 89.152.172.21 è in! leggere vicino Blockquote

se avessi lasciato lavorare per un'ora, moltiplicare "leggere" il 60 e "l'invio di N + 1 al server" , ma questo mostra solo dopo calzino vicino (o stoping il tempo)

+1

Puoi postare che cosa "echos" sputa quando lo esegui? Potrebbe essere utile per il debugging. – xil3

+0

ha aggiornato il post per fare in modo che 'echos' sputi :) – MoshMage

risposta

2

Hai "semplici" socket_write() e socket_read() chiamate.Sfortunatamente le funzioni socket sono non affidabili per la progettazione (il comportamento è ereditato dai socket BSD). Non si può semplicemente chiamare socket_write() e si aspettano di scrivere in realtà byte (come strano come sembra ...) Manuale

PHP citazione:

socket_write() non necessariamente scrivere tutti i byte dal buffer dato. È valido che, a seconda dei buffer di rete ecc., Venga scritta solo una certa quantità di dati, anche un byte, sebbene il buffer sia maggiore. Devi stare attenta a non dimenticarti involontariamente di trasmettere il resto dei tuoi dati.

È necessario verificare quanti byte sono stati scritti e continuare a riprovare finché non è stato inviato tutto ciò che si desidera.

Lo stesso vale per la lettura. Leggi la chiamata può leggere tanto quanto hai richiesto o meno e devi riprovare a chiamare.

Assicurarsi di impostare socket per il blocco e quindi chiamare lettura/scrittura in un ciclo, o utilizzare (altrettanto terribile) select() chiamata per trovare quali socket può hanno alcuni dati o può hanno terminato l'invio.


Se volete API che non è tale valle di lacrime, quindi utilizzare streams, invece, che hanno letture affidabili/scrive.

Se non hai necessariamente bisogno di PHP, dai uno sguardo allo Node JS, che è un server/ambiente appositamente progettato per i programmi con connessioni di rete di lunga durata.

+0

Questo spiega molto. Inoltre, grazie per una risposta così dettagliata, ho perso la speranza di ottenere questo funzionamento :) Effettuerà e controllerà i flussi, come sembra essere più semplice e controllerà anche Node.js perché sembra esattamente quello che voglio – MoshMage

0

Change

socket_write($socket, $i, strlen($i)); 

A:

socket_write($socket, strval($i), strlen(strval($i))); 

Si sta fornendo un intero in cui PHP si aspetta una stringa.

+3

ciò non dovrebbe avere importanza? – zanlok

+0

anche se lo facesse, ottengo ancora i byte 0Rcvd su mIRC – MoshMage

0

Da una delle note nella documentazione: http://php.net/manual/en/function.socket-write.php

Alcuni clienti (XMLSocket di Flash, ad esempio) non viene attivato un evento di lettura fino a quando è ricevuto una nuova linea.

Quindi provare a cambiare il tuo codice:

socket_write($socket, $i, strlen($i)); a: socket_write($socket, $i.'\n', strlen($i)+1);

+0

Doppi apici per una vera newline. – igorw