Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Mój pierwszy serwer w PHP...
Próbowałeś/aś napisać własny serwer w PHP?
Próbowałeś/aś napisać własny serwer w PHP?
Tak [ 8 ] ** [12.70%]
Nie [ 52 ] ** [82.54%]
Próbowałem/am, ale mi nie wyszło... [ 3 ] ** [4.76%]
Suma głosów: 40
Goście nie mogą głosować 
Bakus
post
Post #1


Administrator serwera


Grupa: Przyjaciele php.pl
Postów: 909
Pomógł: 0
Dołączył: 12.08.2003
Skąd: /var/www/wroclaw.php

Ostrzeżenie: (0%)
-----


Serwer (Wywoływany jako "php -q serwer.php"):
  1. <?php
  2. if(!extension_loaded('sockets'))
  3. dl(&#092;"php_sockets.dll\");
  4.  
  5. error_reporting (E_ALL);
  6.  
  7. $address = '192.168.0.1';
  8. $port = 522;
  9.  
  10. print 'Uruchamianie serwera';
  11.  
  12. if (($sock = socket_create(AF_INET, SOCK_STREAM, 0)) < 0)
  13. echo &#092;"nnsocket_create() failed: reason: \" . socket_strerror ($sock) . \"n\"; else print '.';
  14.  
  15. if (($ret = socket_bind($sock, $address, $port)) < 0)
  16. echo &#092;"nnsocket_bind() failed: reason: \" . socket_strerror($ret) . \"n\"; else print '.';
  17.  
  18. if (($ret = socket_listen($sock, 5)) < 0)
  19. echo &#092;"nnsocket_listen() failed: reason: \" . socket_strerror($ret) . \"n\"; else print '.';
  20.  
  21. do{
  22. if (($msgsock = socket_accept($sock)) < 0)
  23. {
  24. echo &#092;"nnsocket_accept() failed: reason: \" . socket_strerror($msgsock) . \"n\";
  25. break;
  26. }
  27.  
  28. $msg = &#092;"nWelcome to the KAB php Test Server. n\";
  29. socket_write($msgsock, $msg, strlen($msg));
  30. print &#092;"tUser connected\";
  31.  
  32. do{
  33. if (FALSE === ($buf = socket_read ($msgsock, 4096, PHP_NORMAL_READ)))
  34. {
  35. echo &#092;"socket_read() failed: reason: \" . socket_strerror($ret) . \"n\";
  36. break 2;
  37. }
  38. if (!$buf = trim($buf))
  39. {
  40. continue;
  41. }
  42. if ($buf == 'quit')
  43. {
  44. break;
  45. }
  46. if ($buf == 'get')
  47. {
  48. print &#092;"nttWysylanie 'file'...n\";
  49. $message = 'file';
  50. socket_write($msgsock, $message, strlen($message));
  51. print &#092;"ttreadyn\";
  52. if(!(FALSE === ($b = socket_read ($msgsock, 4096, PHP_NORMAL_READ))))
  53. {
  54. $message = 'ok';
  55. socket_write($msgsock, $message, strlen($message));
  56. $f = fopen(&#092;"./\" . $b, \"wb\");
  57. print &#092;"ttTransfering data\";
  58. while(!(FALSE === ($b = socket_read ($msgsock, 10240, PHP_NORMAL_READ))))
  59. {
  60. if($b != &#092;"end\")
  61. {
  62. print '.';
  63. fwrite($f, base64_decode($B));
  64. }else{
  65. print &#092;"nttOtrzymano 'end'...n\";
  66. fclose($f);
  67. break 2;
  68. }
  69. }
  70. print &#092;"tendn\";
  71. }else{
  72. print &#092;"terrorn\";
  73. }
  74. }
  75. if ($buf == 'shutdown')
  76. {
  77. $quit_message = 'Dziękujemy za skorzystanie z naszych usług';
  78. socket_write($msgsock, $quit_message, strlen($quit_message));
  79. socket_close($msgsock);
  80. print 'Zatrzymywanie serwera';
  81. break 2;
  82. }
  83. $talkback = &#092;"> '$buf'.n\";
  84. socket_write($msgsock, $talkback, strlen($talkback));
  85. echo &#092;"$bufn\";
  86. }while(true);
  87. print &#092;"tUzytkownik rozlaczonynn\";
  88. print &#092;"Oczekiwanie na nastepne polaczenien\";
  89. socket_close ($msgsock);
  90. }while(true);
  91. socket_close ($sock);
  92.  
  93. print &#092;"...EOSnn\";
  94. ?>


Klient (przez www):
  1. <PRE><?php
  2. $plik = &#092;"do_przeslania.zip\";
  3. $sciezka = &#092;"./\";
  4.  
  5. $s = fsockopen('192.168.0.1', 522, $error, $errno, 10);
  6. print fread($s, 2048);
  7. fputs($s, 'get');
  8. if(fread($s, 2048) == &#092;"file\")
  9. {
  10. fputs($s, $plik);
  11. if(fread($s, 2048) == &#092;"ok\")
  12. {
  13. $fp = fopen($sciezka . $plik, &#092;"rb\");
  14. while (!feof($fp))
  15. {
  16. fputs($s, base64_encode(fgets($fp, 8196)));
  17. }
  18. fclose($fp);
  19. fputs($s, 'end');
  20. fputs($s, 'quit');
  21. fclose($s);
  22. }else{
  23. fputs($s, 'quit');
  24. fclose($s);
  25. }
  26. }else{
  27. fputs($s, 'quit');
  28. fclose($s);
  29. }
  30. ?></PRE>


Klient wysyła zawartość pliku odczytanego z dysku na serwer.
Serwer jest jednowątkowy piki co, ale jak na pierwsze moje dzieło z użyciem socket_* to chyba nieźle...

Byłbym wdzięczny za poprawki do tego wspaniałego (moim skromym zdaniem) serwera...
Klient będzie docelowo napisany w php-GTK, tak by odczytywać pliki z dysków użytkowników...

Celem jest stworzenie uploadera w php-GTK (klient) i php (serwer).

Klient tutaj zamieszczony jest (jak już wspomniałem) dla potrzeb testów...

Najbardziej liczę na waszą pomoc jeżeli chodzi o dodanie wielowątkowości do serwera - tak by naraz z niego mogło korzystać wiele osób.
Jeżeli okaże się to niemożliwe, to proszę o podpowiedź w jaki sposób można "zablokować" serwer przed kolejnymi uploadami (tak, by klient wiedziałm że serwer jest wykorzystywany przez kogoś innego i musi poczkać)

<b>Właśnie - najważniejsza sprawa - serwer jest pod windowsa!</b>
Nie mam zielonego pojęcia, czy i w jaki sposób będzie działał pod linuxem...

UpDated: malutki bug w kliencie - nazwy zmiennych
UpDated: dodanie "if mod loaded = false"...
Uaktualniłem BBCode do wersji z IPB...
(IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
adwol
post
Post #2





Grupa: Zarejestrowani
Postów: 691
Pomógł: 0
Dołączył: 6.08.2003

Ostrzeżenie: (0%)
-----


Cytat
Najbardziej liczę na waszą pomoc jeżeli chodzi o dodanie wielowątkowości do serwera - tak by naraz z niego mogło korzystać wiele osób.

Zainteresuj się funkcją socket_select. Nie daje to prawdziwej wielowątkowości (nie są tworzone osobne wątki ani procesy dla każdego requestu), ale pozwala na obsługę wielu połączeń w obrębie jednego procesu. Niestety php w wersji 4 na windows nie ma porządnego wsparcia do tworzenia wątków i procesów (o funkcjach exec i system nie mówimy). Rozszerzenie pctnl w którym jest funkcja pctnl_fork istnieje tylko w wersji uniksowej, więc z niej nie skorzystasz. Będziesz się musiał zadowolić praktyczne chyba tylko selectem.
Cytat
Właśnie - najważniejsza sprawa - serwer jest pod windowsa!Nie mam zielonego pojęcia, czy i w jaki sposób będzie działał pod linuxem...

Sockety pochodzą orygnialnie z uniksa (dokładniej z BSD) i uniksy są ich ojczyzną. Jeśli pracuje to prawidłowo na windowsie to na linuksie też nie będzie większych problemów. (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Z ogólnych uwag:
:arrow: Masz troche bałaganu w kodzie. Napisałeś to bez użycia chociażby jednej funkcjii, że o klasach nawet nie wspomnę.
:arrow: Ustal sobie najpierw jakiś protokół komunikacji (możesz bazować na HTTP). Wymyśl jak będzie przebiegała transmisja i komunikacja, jakie będą wydawane komendy, itp. Np. niech będą na początek dwie istotne komendy: GET i PUT (znaczenie wiadome). Parametry do tych komend (np. nazwy plików) staraj się dawać w jednej linii z komendą, np.:
Kod
GET plik.txt

Niech serwer odpowiada coś po każdym wysłanym żądaniu od klienta. Linie z odpowiedzią niech będą poprzedzane jakimś kodem statusu operacji. Będzie im wtedy łatwiej się ,,dogadać'' przy bardziej rozbudowanym protokole, reagować na błędy, itp. Np.: (S -- server, K -- klient)
Kod
S: 00 Witamy na naszym serwerze

K: GET /katalog/plik.txt

S: 10 Błąd. Plik /katalog/plik.txt nie istnieje.

K: GET /katalog/plik2.txt

S: 20 572

S: Pierwsza linia pliku

S: Druga linia pliku

S: Trzecia linia pliku

K: PUT /katalog/plik3.txt 1092

K: Pierwsza linia pliku

K: Druga linia pliku

K: Trzecia linia pliku

S: 30 Dziekuje. Odebrano 1092 bajty danych.

K: QUIT

S: 00 Do widzenia

Generalnie przewiduj rozszerzenie protokołu w przyszłości (chyba, że napewno tego nie chcesz) o np. autoryzacje, listowanie zawartości katalogów, itp. Łatwiej jest później dodać jeden nagłówek w żądaniu, niż przerabiać pół protokołu.
:arrow: Po co kodujesz wysyłane pliki za pomocą base64? Niech klient i serwer wysyłają przed początkiem transmisji długość pliku. W przyszłości być może przyda Ci się to do optymalizacji.
:arrow: Zapisz sobie obsługę każdej komendy jako osobną funkcję ze jednym stałym interfejsem do wszystkich. Główna pętla programu niech tylko obsługuje połączenia i rozdziela zadania pomiędzy funkcje

Możesz mieć problemy z efektywnym wykorzystaniem socket_select(), ale na początek spróbuj chociaż uzyskać wiele połączeń naraz (bez jednoczesnego wysyłania danych).

Dobrze, że ktoś się zainteresował innym wykorzystaniem php niż tylko jako język dynamicznych stron WWW, bo dla większości jest on nieodłącznie związany z tym segementem internetu. Niestety nie był on projektowany do takich zastosowań, ale przy odrobinie chęci da się z tego coś sensownego wykrzesać. (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 11.10.2025 - 22:18