←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

[ROZWIĄZANE] Sockets - problem z lagami

Zablokowany

  • +
  • -
SeeK - zdjęcie SeeK 19.11.2013

Witam,

napisałem sobie ostatnio pewien skrypcik pobierający dane z pliku php, który to natomiast wykonuje główne czynności. Aczkolwiek zanim użyję funkcji sockets_send to sprawdzam, czy dany plik php wogóle istnieje. Tak na wszelki wypadek. Mój kod wygląda tak:

new error, socket
socket = socket_open("xxx.pl", 80, SOCKET_TCP, error)
if(socket < 1) {
client_print(id,print_chat,"[%s] Nie mozna polaczyc sie z serwerem weryfikacyjnym. Sprobuj ponownie pozniej.",PREFIX)
return
}
else {
new sData[256]
format(sData, charsmax(sData),"GET /serwery_teksty/weryfikuj2.php HTTP/1.0^r^n")
format(sData, charsmax(sData), "%sHost: xxx.pl^r^n^r^n", sData)
socket_send(socket, sData, strlen(sData))
 
new sBuffer[40]
socket_recv(socket, sBuffer, charsmax(sBuffer))
if(containi(sBuffer,"404 Not Found") != -1) {
client_print(id,print_chat,"[%s] Nie mozna znalezc pliku weryfikacyjnego. Zglos nam ten blad: %s",PREFIX,kontakt)
return
}
}
[...]
Odpowiedz

  • +
  • -
sebul - zdjęcie sebul 19.11.2013

Ale jakie jest pytanie?
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 19.11.2013

Pytanie oczywiste: dlaczego mam laga, gdy używam socketów. Zastanów się dlaczego są lagi, gdy używa się MySQL bez ThreadQuery, tu odpowiedź jest taka sama :)

 

Jednak tu nie mamy czegoś takiego, jak ThreadQuery i trzeba radzić sobie inaczej...

 

Jest natomiast funkcja socket_change, która tylko sprawdza, czy coś nowego nie przyszło, więc robimy tak: ustawiamy sobie socket_open i socket_send w jednej funkcji, a zamiast socket_recv ustawiamy taska. W tasku wywołujemy socket_change, jeśli zwróci, że nic nie przyszło, odpalamy następnego taska, jeśli przyszło, socket_read i robimy co sobie tam chcemy z tym, co przyjdzie albo wysyłamy coś nowego, albo czekamy na następne dane... To już od Ciebie zależy.

 

Zamiast taków można wrzucić to w jakiegoś thinka, server_frame czy inne często wykonujące się funkcje, jednak server_frame będzie do tego zdecydowanie zbyt często się wykonywał. Task natomiast ciut zbyt rzadko :)

Odpowiedz

  • +
  • -
SeeK - zdjęcie SeeK 20.11.2013

Sebul pytanie było takie jak GwynBleid napisał. Czyli dlaczego mam lagi. Niestety u Was na forum występuje taki niefajny błąd, że podczas pisania nowego tematu wszystko po znaczniku [ code][ /code] znika. A moje pytanie było właśnie napisane poniżej kodu.

Wracając do tematu. GwynBleid dzięki wielkie za podpowiedź, przetestuje, czy to wyeliminuje błąd :)
Odpowiedz

  • +
  • -
sebul - zdjęcie sebul 20.11.2013

Jak dla mnie najlepiej jest użyć dwóch tasków, czyli, np.
(...)
set_task(0.6, "handleCheckData", TASK_ZG, data, 1, "b");
set_task(10.0, "handleEnd", TASK_ZG2, data, 1);
(...)
public handleEnd(data[1]) {
remove_task(TASK_ZG);
socket_close(g_socket);
g_socket = 0;

// jakieś info o niepowodzeniu
}

public handleCheckData(data[1]) {
if(!socket_change(g_socket)) {
return;
}

remove_task(TASK_ZG);
remove_task(TASK_ZG2);

new szData[256];
socket_recv(g_socket, szData, 255);
socket_close(g_socket);
g_socket = 0;

// operacje na tym co zostało zwrócone
}

A co do tego else co masz w kodzie, to jest one nie potrzebne, skoro w warunku masz return.
Odpowiedz

  • +
  • -
DarkGL - zdjęcie DarkGL 20.11.2013

Czyli dlaczego mam lagi.

 

Ponieważ w ten sposób urzyte sockety są synchroniczne czyli serwere czeka aż przyjdą dane nie wykonując żadnego innego kodu więc tak naprawdę nie są to lagi tylko proces "wisi" w jednym miejscu

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 20.11.2013

Oczywiście, sebul dobrze rozwinął moją myśl... Dodatkowy task dla obsługi timeouta może się przydać, jednak można zrobić to w jednym tasku, zliczając ile razy się już wykonał :)

co do błędu z:
kodem
Nigdy nie miałem z tym problemów... Może pozwolisz, abym używając TeamViewera zobaczył na czym dokładnie polega ten błąd, może uda się go wtedy rozwiązać.
Odpowiedz

  • +
  • -
SeeK - zdjęcie SeeK 21.11.2013

GwynBleidD nie ma sprawy, napisz na PW, to możemy ustalić "meeting" ;]

 

 

Czyli dlaczego mam lagi.

 

Ponieważ w ten sposób urzyte sockety są synchroniczne czyli serwere czeka aż przyjdą dane nie wykonując żadnego innego kodu więc tak naprawdę nie są to lagi tylko proces "wisi" w jednym miejscu

 

 

Zadałem złe pytanie. Wiem dlaczego mam lagi. Pytanie miało brzmieć, jak się ich pozbyć, jak stworzyć nowy wątek w którym serwer będzie oczekiwał na odpowiedź :) Btw. użyte przez 'ż' się pisze ;]

 

Co do else, to wiem, że jest niepotrzebny, ale nie robi on tam krzywdy, a dla mnie kod jest wtedy bardziej czytelny :)

 

---------------

 

Mam jeszcze jedno pytanie, jak przekazywać uchwyt do połączenia pomiędzy funkcjami? Zadeklarować go globalnie czy poprzez tablice w tasku?


Użytkownik SeeK edytował ten post 21.11.2013 21:53
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 23.11.2013

Tablica w tasku, oczywiście! Po co zaśmiecać kod zmiennymi globalnymi? Jeśli masz możliwość przekazania przez taką tablicę czegoś, zawsze to wykorzystuj... gdy powstanie Ci kilka połączeń na raz będziesz budował tablicę globalną na to wszystko?

Odpowiedz

  • +
  • -
SeeK - zdjęcie SeeK 24.11.2013

No to wszystko jasne. Dzięki wszystkim za pomoc :)
Odpowiedz

  • +
  • -
sebul - zdjęcie sebul 24.11.2013

Wiadomość wygenerowana automatycznie


Ten temat został zamknięty przez moderatora.

Powód: Pomoc udzielona

Jeśli się z tym nie zgadzasz, report.png raportuj ten post, a moderator lub administrator rozpatrzy go ponownie.


Z pozdrowieniami,
Zespół AMXX.PL
Odpowiedz
Zablokowany