Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Stałe połączenie z serwerem
Forum PHP.pl > Forum > PHP
kamil4u
Witam.

Potrzebuję nawiązać stałe połączenie z serwerem, niestety wszelkie moje próby spełzły na niczym.

Robię konsolę, która umożliwi mi wysłanie i otrzymywanie danych z serwera. Idea działania jest taka:
Kod
connect 192.163.0.153 500 <-- połączenie z serwerem o ip 92.163.0.153 - port 500
-- connection set
send 123456 <-- wysłanie danych do serwera 123456
-- 654321 <-- odpowiedź serwera


Wszystkie ip, porty czy dane na forum są fikcyjne.

Problem polega na tym, że każde polecenie( connect, send) to nowe zapytanie do serwera(PHP) przez AJAX. Gdy mój kod PHP wygląda mniej więcej tak:
  1. <?php
  2. if( isset($_POST['name']) && !empty($_POST['name']) ){
  3. $name = $_POST['name']; // $name to nazwa funkcji <-> connect, send
  4.  
  5. if( isset($_POST['data']) && !empty($_POST['data']) )
  6. $data = $_POST['data']; //$data to parametry np. dla connect w powyższym przykładzie będzie to ciąg: '192.163.0.153,500'
  7.  
  8. require_once('./klasa.php');
  9.  
  10. switch( $name ){
  11. case 'connect':
  12. $data = explode( ',',$data );
  13. $connection = klasa::connect( $data[0],$data[1] );
  14. if( $connection ){
  15. $_SESSION['connection'] = $connection; //!!!
  16. echo 'connection set';
  17. } else
  18. echo 'error: connection lost';
  19. break;
  20.  
  21. case 'send':
  22. $fp = $_SESSION['connection']; //!!!
  23.  
  24. $zmienna = explode(',',$data);
  25. var_dump( $_SESSION['connection'] ); //wyświetla zawsze 0
  26.  
  27. //różnego rodzaju operacje
  28. fgets($fp, $zmienna);
  29. $x = fread($fp, 8192);
  30.  
  31. echo $x;
  32. break;
  33.  
  34. default:
  35. break;
  36. }
  37. }
  38. ?>

Plik klasa.php jest bardzo prosty:
  1. <?php
  2. class klasa{
  3.  
  4. public static function connect( $id,$port ){
  5. $connection = stream_socket_client( 'tcp://'.$id.':'.$port,$errno,$errstr );
  6.  
  7. if( $connection )
  8. return $connection;
  9. else
  10. return false;
  11. }
  12. }
  13. ?>


Jak widać łączę się z serwerem za pomocą stream_socket_client i próbuję utworzone połączenie zapisać w sesji "$_SESSION['connection'] = $connection;". Następnie w kolejnym zapytaniu( AJAX, konsola -> funkcja send) próbuję "odzyskać" to połączenie poprzez "$fp = $_SESSION['connection'];"

Jednak wtedy uzyskuje błąd, że pierwszy parametr w funkcjach fgets i fread jest nieprawidłowy - jak pisałem przyjmuje wartość (int)0.

Próbowałem chyba wszystkiego stream_socket_client, stream_socket_server, fsockopen, pfsockopen, jednak nie udało mi się osiągnąć zamierzonego efektu.

Jak mimo zakończenia działania skryptu PHP utworzyć stałe połączenie z serwerem, które będzie przechowywane w sesji?

Pozdrawiam i z góry dziękuje z odpowiedzi.

PS. Jestem pewien, że sama funkcja send działa prawidłowo.
Fifi209
Zapisz uchwyt do sesji. ;]
kamil4u
No, ale przecież tak robię...
  1. Linia 16: $_SESSION['connection'] = $connection; //!!!
  2. Linia 23: $fp = $_SESSION['connection']; //!!!


No chyba, że robię to źle, ale nie wydaje mi się. Moim zdaniem połączenie jest zamykane w chwili zakończenia skryptu PHP i sesja tu nie pomoże.
Funkcja pfsockopen teoretycznie powinna być idealna, ale albo ja nie umiem z niej korzystać, albo nie rozumiem jak działa - wtedy prosiłbym o wytłumaczenie. Próbowałem też w stream_socket_client skorzystać z flagi: STREAM_CLIENT_PERSISTENT ,ale efekt uzyskuje ten sam: w sesji znajduje się wartość: (int) 0.

Zastanawiałem się, że może te funkcje( pfsockopen ) gdzieś na serwerze zapisują informację o otwartym połączeniu i gdy 2 raz wywołam tę samą funkcję, to wtedy połączenie nie jest otwierane na nowo, ale "brane" z tego zapisu - ale nigdzie nie widzę potwierdzenia tych słów, a nie mam za bardzo jak tego sprawdzić...

Proszę o jakieś wskazówki.

--Edit--
Sesje też na pewno działają prawidłowo

--Edit--
Błędy - jak widać potwierdzają to co mówię - w sesji jest (int 0):
Kod
Warning: fgets() expects parameter 1 to be resource, integer given in /var/www/php/console.php on line 29
Warning: fread() expects parameter 1 to be resource, integer given in /var/www/php/console.php on line 30
wookieb
Cytat(Fifi209 @ 9.06.2011, 15:11:46 ) *
Zapisz uchwyt do sesji. ;]

Sesja jest serializowana. Resource-y (uchwyty) nie mogą być serializowane. Nic do nie da. Preferowałbym jakiś middleware.
Kuziu
Oczywiście że jest zamykane po zakończeniu skryptu, tak to by wisiało mnóstwo połączeń nie zamkniętych.
Fifi209
Kuziu, nikt tu o zamykaniu nic nie pisał tylko o serializacji sesji i o tym, że uchwyty serializowane być nie mogą.
kamil4u
A nie można jakoś wymusić niezamknięcia połączenia? Po co są te funkcje, które podałem, skoro jak mniemam "nic nie dają"? Mógłby ktoś napisać na ten temat coś więcej - nigdy nie miałem doświadczenia z takimi połączeniami, a w internecie zbyt dużo informacji nie ma.

Szczególnie chodzi mi o funkcję pfsockopen, gdzie w manualu ,jest napisane: "Open persistent Internet or Unix domain socket connection" - jak z niej skorzystać, abym mógł osiągnąć to co chcę - niekoniecznie musi to być sesja.

@fifi209: ja pisałem wink.gif - "Moim zdaniem połączenie jest zamykane w chwili zakończenia skryptu PHP i sesja tu nie pomoże."

@wookieb: Ale jakie(middleware) ? Jak pisałem mam niewielkie doświadczenie pod tym względem. Przyjmę każdą radę.
KrzysiekWildfire
Widziałem coś takiego do zarządzania serwerem counter strike'a, z tą różnicą, że tam był (z tego co mi się wydaje) java applet - i chyba jest to najlepsze rozwiązanie w takich sytuacjach.
kamil4u
@KrzysiekWildfire: dzięki za odpowiedź, jednak to mi nie pomaga.

Jakby ktoś mi powiedział jak to wszystko działa byłoby super.
sh3d2
Cytat(kamil4u @ 9.06.2011, 18:57:05 ) *
Jakby ktoś mi powiedział jak to wszystko działa byłoby super.


Wg mnie (oczywiscie moge sie mylic) jest to tak, ze nie musisz (a nawet nie mozesz - nie jestes w stanie) zapisac hooka jako zmiennej sesyjnej, bo jak ktos wyzej madrze powiedzial, to jest resource.
pfsockopen() czy wszystkich innych p*() uzywasz dokladnie tak samo jak ich "tymczasowych" (bez p) odpowiednikow, php samo za ciebie skorzysta z istniejacego polaczenia (zamiast przy wywolaniu p*() tworzyc nowe) jesli takowe znajdze.

kiedy "nic z tego nie bedzie" znajdziesz tu: http://www.php.net/manual/en/function.pfsockopen.php#76716
pozdrawiam
kamil4u
Sprawdziłem, jest tak jak piszesz - wcześniej też się tego "domyślałem", ale nie znalazłem dowodu. Dopiero wczoraj sprawdziłem dokładnie komentarze -. Zacząłem się interesować jak to sprawdzić. W pierwszym komentarzu dano wskazówkę, żeby sprawdzić to za pomocą funkcji ftell. Jako, że nie za bardzo jeszcze się orientuję w tych wszystkich funkcjach( i nie do końca rozumiem, co jest napisane w tych komentarzach - dodając techniczne sprawy + ang zaczynam się gubić smile.gif ), trochę zeszło zanim napisałem kod "udowadniający" to co napisałeś.

Podsumowującpfsockopen działa tak, że przy pierwszym połączeniu nie zamyka go, a żeby "ponownie" zdobyć uchwyt do niego, należy po prostu wywołać jeszcze raz tę funkcję, a PHP "domyśli się", że to połączeni jest już otwarte i tylko zwróci nam uchwyt.

Trzeba pamiętać, że trzeba zamknąć takie połączenie.

Bardzo dziękuję!
Pozdrawiam
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.