2010-11-09 9 views
5

Bearbeiten: Sorry, versehentlich mit einem Titel für eine andere Frage geschrieben. Fest.Kann nicht aus Socket lesen (hängt)

Hey Jungs,

ich mit PHP bin zu einem lokalen C++ Socket-Server zu halten Zustand zwischen einem Web-App und ein paar Dämonen zu verbinden. Ich kann Daten an den Socket-Server senden, aber nicht von ihm erhalten; Es blockt nur auf socket_read() und hängt unbegrenzt. Vergesse ich etwas Dummes (wie ein NULL-Zeichen oder eine andere Kombination von Newline-Zeichen)? Die PHP ist unter:

socket_connect($sock, $addr, $port); 
socket_write($sock, 'Hello world'); 
$str = ''; 
while($resp = socket_read($sock, 1000)) 
    $str .= $resp; 
socket_close($sock); 
die("Server said: {$str}"); 

Der entsprechende Teil des Socket-Server ist unter (beachten Sie, dass die << und >> Betreiber überlastet sind):

std::string data; 
sock >> data; 
sock << data << std::endl; 

Wo >> Anrufe Socket::recv(std::string&) und >> Anrufe Socket::send(const std::string&).

Dies funktioniert gut aus (zum Beispiel) Telnet, aber PHP will nicht nett spielen. Irgendwelche Gedanken/Vorschläge werden geschätzt.

+1

Welche Socket-Bibliothek verwenden Sie für C++ oder haben Sie eigene (* nix oder Windows) erstellt? Was ist der Fehler? Blockiert es für immer auf Socken >> Daten oder ist etwas mehr passiert? Ich habe schon lange keine PHP-Kommunikation mit einem C++ - Server mehr verwendet, aber sendet Ihr Server eine Terminierung an den Socket, damit PHP nicht mehr lesen kann? Ihre Schleife wird kontinuierlich in PHP gelesen, bis der Server sagt, dass der Socket fertig ist, Informationen zu senden; Es ist kein Echtzeit-Update, das Sie beachten (da es die Daten ausgibt, nachdem sie vollständig gesammelt und in Ihrem var gespeichert wurden). – RageD

+0

Dies könnte nur in Ihrem Code fehlen, aber haben Sie zuerst 'socket_create' $ Socke? – netcoder

+0

Auch ich sehe das nicht in Ihrem Code, aber Sie müssen $ str drucken, wenn Ihre Schleife abgeschlossen ist. – RageD

Antwort

7

Sockets in PHP , wie in den meisten Programmiersprachen, werden standardmäßig im Blockiermodus geöffnet, sofern nicht anders eingestellt unter Verwendung von socket_set_nonblock.

Dies bedeutet, dass socket_read für immer dort hängen bleibt, wenn ein Timeout/Fehler auftritt oder Daten empfangen werden.

Da Ihr Abschlusszeichen scheint eine neue Linie zu sein, versuchen Sie, dass:

while($resp = socket_read($sock, 1000)) { 
    $str .= $resp; 
    if (strpos($str, "\n") !== false) break; 
} 
socket_close($sock); 
die("Server said: $str"); 
+0

Tatsächlich wusste ich, dass sie standardmäßig blockieren, aber ich habe komplett vergessen, entweder a) den Socket zu schließen, nachdem die Antwort geschrieben wurde, oder b) die Schleife zu unterbrechen. Dank dafür. Die Verwendung eines NULL-Zeichens scheint nicht zu funktionieren, wenn ich es umschalte (im Idealfall wäre es kein Zeilenumbruch) - wenn ich nach 'sock << data mway

+0

Im Gegensatz zu C oder C++ schreibt PHP keine Nullbytes am Ende von Strings, deshalb liefert 'strpos' mit' \ 0' im Test Boolean false. Sie müssen ein anderes Trennzeichen angeben, ein Timeout verwenden (siehe [Wie setze ich ein Timeout beim Socket-Lesen?] (Http://StackOverflow.com/questions/389645/)) oder schließe den Socket von der Server-Seite. – netcoder

+0

Schön genug - das wurde mir gerade durch Tests bewusst. Danke für Ihre Hilfe! – mway

0

Ich habe gerade ein Problem ähnlich, nur mit Rohren (Is php's fopen incompatible with the POSIX open for pipes) behoben. Ich weiß nicht, in welchem ​​Ausmaß die Lösung ähnlich wäre, aber vielleicht einen Blick wert? Ich stimme RageD zu, dass Sie einen cout zwischen den Lese- und Schreibleitungen stecken sollten, nur um zu testen, ob das C++ an der Socke hängt >> Datenleitung oder die Socke <

1

TCP-Sockets in der Regel versuchen, mehr kleine Anrufe senden in ein Paket zu kombinieren, zu viele Pakete (Nagle's algorithm) zu vermeiden, senden. Dies kann die Ursache sein, dass Sie nach dem Aufruf von send() nichts empfangen können. Sie müssen den Sockel mit TCP_NODELAY öffnen, um dies zu vermeiden.

0

Sie können dies auch versuchen, wenn aus der Steckdose zu lesen:

if(socket_recv ($socket , $response , 2048 , MSG_PEEK)!==false) 
{ 
    echo "Server said: $response"; 
} 

Hinweis: MSG_WAITALL anstelle von MSG_PEEK verwenden, kann Buchse dazu führen, (ich hatte einmal von einer Erfahrung) zu hängen.

Verwandte Themen