Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] Klient -> Serwer
Forum PHP.pl > Forum > PHP
gutek84
Czy możliwe jest wykonanie w php aplikacji klient -> serwer?
Mam napisane 2 klasy.
Klasa serwer:
  1. <?php
  2. class Serwer{
  3.  
  4. private $gniazdko;
  5. private $adres = '127.0.0.1';
  6. private $port = 80;
  7. public $odebrane;
  8.  
  9. public function uruchomSerwer(){
  10. //Utworzenie gniazdka dla polaczenia TCP
  11. $this->gniazdko = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  12. socket_bind($this->gniazdko, $this->adres);
  13. socket_listen($this->gniazdko);
  14. if($this->gniazdko!== FALSE)echo "Uruchomiono!";
  15. }
  16.  
  17. public function odebrane(){
  18. socket_accept($this->gniazdko);
  19. $this->odebrane = socket_read($this->gniazdko, 2048);
  20. }
  21.  
  22. public function wylaczSerwer(){
  23. socket_close($this->gniazdko);
  24. echo "Zatrzymano!";
  25. }
  26.  
  27.  
  28. }
  29. ?>


Klasa Klient

  1. <?php
  2. class Klient{
  3. public $gniazdko;
  4. public $odebrane;
  5.  
  6. public function polacz($host){
  7. //Pobranie portu dla www
  8. $port = getservbyname('www', 'tcp');
  9. //pobranie adresu serwera
  10. $serwer = gethostbyname($host);
  11. //Utworzenie gniazdka dla polaczenia TCP
  12. $this->gniazdko = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  13. //Utworzenie połączenia
  14. $polaczenie = socket_connect($this->gniazdko, $serwer, $port);
  15. if($polaczenie!==False)echo"Polączono z serwerem!";
  16.  
  17. }
  18.  
  19.  
  20. public function rozlacz(){
  21. //Pobranie portu dla www
  22. socket_close($this->gniazdko);
  23.  
  24. }
  25.  
  26. public function wyslij($pakiet){
  27. //wysłanie danych
  28. socket_write($this->gniazdko, $pakiet, strlen($pakiet));
  29. }
  30.  
  31. public function odbierz(){
  32. //odbiór danych
  33. while($this->odebrane = socket_read($this->gniazdko, 2048)){
  34. echo $this->odebrane;
  35. };
  36. }
  37. }
  38. ?>


Problem następuje w momencie kiedy próbuje przesłać zapytanie od klienta do serwera! Nie wyskakują żadne warningi a skrypt serwera jakby sie wieszal w momencie proby odczytu!
Tak samo skrypt klienta w momencie wysylania takze sie zawiesza.

Prosze o pomoc!
Kicok
Nie wiem dokładnie co może być przyczyną tego zawieszania, bo nie pokazałeś nam najistotniejszego kodu - wywołania metod tych klas. Mogę co najwyżej przypuszczać, że dzieje się coś takiego:
- serwer nasłuchuje
- klient łączy się i wysyła powiedzmy 20 bajtów danych
- serwer odbiera te 20 bajtów, ale nie wie że to już koniec i czeka na następne
- klient w tym czasie czeka na odpowiedź serwera, więc nie zamyka połaczenia
- wszystko wisi


Wyjścia z tej sytuacji:
- Połączenia nieblokujące się, z tym że ty najprawdopodobniej chcesz, żeby serwer sobie działał gdzieś w tle i czekał spokojnie na połączenia. Wtedy coś takiego odpada. No ale poczytać możesz: (socket_set_nonblock" title="Zobacz w manualu PHP" target="_manual, socket_set_block" title="Zobacz w manualu PHP" target="_manual)
- Klient po wysłaniu danych nie czeka na odpowiedź tylko od razu zamyka połączenie (też w sumie odpada, bo wyjdzie z tego komunikacja jednostronna)
- Po wysłaniu danych wysyłasz jeszcze NULL (0x00). Serwer napotykając NULL kończy odbieranie danych i wysyła odpowiedź (też zakończona NULL-em). Problem jest taki, że NULL nie może wystąpić w przesyłanych danych
- I najlepsze: ustalasz sobie jakąś strukturę pakietów przesyłanych między serwerem a klientem, np:
Kod
Nagłówek
- typ_pakietu [1 bajt]
- długość_pakietu [4 bajty]
Ciało
- treść_pakietu [długość_pakietu]

Po odczytaniu długości ciała pakietu zarówno serwer jak i klient wiedzą ile jeszcze bajtów danych muszą odebrać. Przydatne funkcje: pack" title="Zobacz w manualu PHP" target="_manual, unpack" title="Zobacz w manualu PHP" target="_manual


PS. socket_get_option" title="Zobacz w manualu PHP" target="_manual i socket_set_option" title="Zobacz w manualu PHP" target="_manual też mogą się przydać.
gutek84
Zmienilem klase Serwer na
  1. <?php
  2. class Serwer{
  3.  
  4. private $gniazdko;
  5. private $adres = '127.0.0.1';
  6. private $port = 80;
  7. public $odebrane;
  8.  
  9. public function uruchomSerwer(){
  10. //Utworzenie gniazdka dla polaczenia TCP
  11. $this->gniazdko = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  12. socket_set_blocking($this->gniazdko);
  13. socket_set_option($this->gniazdko, SOL_SOCKET, SO_REUSEADDR, 1);
  14. socket_bind($this->gniazdko, $this->adres, $this->port);
  15. socket_listen($this->gniazdko,1);
  16.  
  17. while(true){
  18.  
  19. $klient =socket_accept($this->gniazdko);
  20. echo "klient przyszedl";
  21. }
  22. if($this->gniazdko!== FALSE)echo "Uruchomiono!";
  23. }
  24.  
  25. public function odebrane(){
  26.  
  27. while($this->odebrane = socket_read($this->gniazdko, 2048)){
  28. echo $this->odebrane;
  29. };
  30.  
  31. }
  32.  
  33. public function wylaczSerwer(){
  34. echo "Zatrzymano!";
  35. socket_close($this->gniazdko);
  36.  
  37.  
  38.  
  39. }
  40.  
  41. }
  42.  
  43. ?>


Wiec nie dostaje zadnych bledow przy serwerze i kliencie. Jednak kiedy klient wysyla to serwer nie odbiera. Polaczenie jest akceptowane lecz nie ma komunikacji miedzy stronami. Uzywam socket_read i socket_write do przesylania danych.

Druga strona to jak mozna zrobic dynamiczny serwer.
Ten powyzszy dziala jak mam timeout na 10 to wyglada jakby przez 10 sekund ladowala sie strona. Interesuje mnie klient przychdzi i od razu go widze np. przed uplywem 10 sekund.
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.