2012-10-13 9 views
6

Zaimplementowałem klienta/serwer, który komunikuje się za pomocą gniazda TCP. Dane, które zapisuję w gnieździe, to JSON. Początkowo wszystko działa zgodnie z oczekiwaniami, jednak gdy zwiększam szybkość zapisu, w końcu napotkam błędy analizy JSON, gdzie początek na kliencie otrzymuje początek nowego zapisu na końcu starego.Problemy podczas odczytywania ciągu znaków z gniazda TCP w pliku Node.js

Oto kod serwera:

var data = {}; 
data.type = 'req'; 
data.id = 1; 
data.size = 2; 
var string = JSON.stringify(data); 
client.write(string, callback()); 

Oto jak ja otrzymuję ten kod na serwerze klienta:

client.on('data', function(req) { 
    var data = req.toString(); 
    try { 
     json = JSON.parse(data); 
    } catch (err) { 
     console.log("JSON parse error:" + err); 
    } 
}); 

Błąd, że jestem otrzymania wraz ze wzrostem stawki wynoszą:

SyntaxError: Unexpected token { 

który wydaje się być początkiem następnego żądania są oznaczone na koniec bieżącego jeden.

Próbowałem używać; jako ogranicznik na końcu każdego żądania JSON, a następnie przy użyciu:

var data = req.toString().substring(0,req.toString().indexOf(';')); 

Jednak to podejście, a nie w wyniku błędów analizy JSON wydaje się prowadzić do całkowicie brakuje niektórych żądań po stronie klienta, jak zwiększyć szybkość pisze ponad 300 na sekundę.

Czy istnieją jakieś sprawdzone metody lub bardziej skuteczne sposoby ograniczania przychodzących żądań za pośrednictwem gniazd TCP?

Dzięki!

+0

Istnieją dwa Podobne pytania [[1] (http://stackoverflow.com/questions/ 9962197/node-js-readline-not-waiting-for-a-full-line-on-socket-connections), [2] (http://stackoverflow.com/questions/7034537/nodejs-what-is-to -proper-way-to-handling-tcp-socket-streams-which-delimiter)]. W obu z nich rozwiązaniem jest użycie ograniczników oraz przechowywanie resztek poprzedniego komunikatu. Niestety, lepsze rozwiązanie nie wydaje się jeszcze istnieć. – mayconbordin

Odpowiedz

23

Dziękuję wszystkim za wyjaśnienia, pomogli mi lepiej zrozumieć sposób, w jaki dane są wysyłane i odbierane przez gniazda TCP. Poniżej znajduje się krótki przegląd kodu, który kiedyś w końcu:

var chunk = ""; 
client.on('data', function(data) { 
    chunk += data.toString(); // Add string on the end of the variable 'chunk' 
    d_index = chunk.indexOf(';'); // Find the delimiter 

    // While loop to keep going until no delimiter can be found 
    while (d_index > -1) {   
     try { 
      string = chunk.substring(0,d_index); // Create string up until the delimiter 
      json = JSON.parse(string); // Parse the current string 
      process(json); // Function that does something with the current chunk of valid json.   
     } 
     chunk = chunk.substring(d_index+1); // Cuts off the processed chunk 
     d_index = chunk.indexOf(';'); // Find the new delimiter 
    }  
}); 

Komentarze mile widziane ...

+0

+1 świetnie! to rozwiązało mój długo oczekiwany ten sam problem. Dzięki. – ajay

+0

Dobra odpowiedź, dzięki! –

+1

Po próbie dodaj instrukcję catch ... –

-3

Spróbuj z end imprezy i żadnych danych

var data = ''; 

client.on('data', function (chunk) { 
    data += chunk.toString(); 
}); 

client.on('end', function() { 
    data = JSON.parse(data); // use try catch, because if a man send you other for fun, you're server can crash. 
}); 

Nadzieja pomóc.

+0

To nie działa z nodejs w komunikacji gniazda –

5

Jesteś na dobrej drodze dzięki użyciu ogranicznika. Jednak nie możesz po prostu wyodrębnić rzeczy przed ogranicznikiem, przetworzyć go, a następnie odrzucić to, co przyszło po nim. Musisz buforować wszystko, co masz, po separatorze, a następnie połączyć to, co jest obok niego. Oznacza to, że możesz skończyć z dowolną liczbą (w tym 0) "kawałków" JSON po danym wydarzeniu data.

Zasadniczo przechowujesz bufor, który zainicjujesz na "". Na każdym zdarzeniu data łączysz wszystkie dane, które otrzymasz na końcu bufora, a następnie bufor na ograniczniku. Wynikiem będzie jeden lub więcej wpisów, ale ostatni może nie być kompletny, więc musisz przetestować bufor, aby upewnić się, że kończy się ogranicznikiem. Jeśli nie, wyskakuj ostatni wynik i ustaw do niego swój bufor. Następnie przetwarzane są wszelkie wyniki (które mogą nie być).

2

Należy pamiętać, że protokół TCP nie gwarantuje, że dzieli porcje danych, które otrzymujesz. Wszystko to gwarantuje, że wszystkie wysłane bajty zostaną odebrane w kolejności, chyba że połączenie nie zakończy się całkowicie.

Wierzę, że zdarzenia Node data pojawiają się za każdym razem, gdy gniazdo mówi, że ma dla Ciebie dane. Technicznie można uzyskać oddzielne zdarzenia dla każdego bajtu w danych JSON i nadal będzie to w granicach tego, co system operacyjny może zrobić. Nikt tego nie robi, ale twój kod musi być napisany tak, jakby mógł nagle zacząć się w każdej chwili stać silny.Od Ciebie zależy łączenie zdarzeń danych, a następnie ponowne rozdzielanie strumienia danych wzdłuż granic, które mają dla ciebie sens.

Aby to zrobić, należy buforować wszelkie dane, które nie są "kompletne", w tym dane dołączone na końcu fragmentu "kompletnych" danych. Jeśli używasz separatora, nigdy nie wyrzucaj żadnych danych po ograniczniku - zawsze trzymaj go jako prefiks, dopóki nie zobaczysz więcej danych i ewentualnie innego ogranicznika lub zdarzenia końcowego.

Innym powszechnym wyborem jest przedrostek wszystkich danych za pomocą pola długości. Powiedzmy, że używasz stałej 64-bitowej wartości binarnej. Następnie zawsze czekają na 8 bajtów, a także o wiele więcej wartości w bajtach, aby przybyć. Powiedzmy, że masz porcję dziesięciu bajtów danych przychodzących. Możesz otrzymać 2 bajty w jednym zdarzeniu, potem 5, następnie 4 - w którym momencie możesz przeanalizować długość i wiedzieć, że potrzebujesz jeszcze 7, ponieważ ostatnie 3 bajty trzeciej porcji były ładunkiem. Jeśli następne zdarzenie faktycznie zawiera 25 bajtów, należy wziąć pierwsze 7 wraz z poprzednimi 3 i przeanalizować je, i poszukać innego pola długości w bajtach 8-16.

Jest to przykładowy przykład, ale należy pamiętać, że przy niskich natężeniach ruchu warstwa sieciowa będzie generalnie wysyłać dane w dowolnych porcjach, więc takie rzeczy zaczynają się pojawiać dopiero po zwiększeniu obciążenia. . Gdy system operacyjny zacznie budować pakiety z wielu zapisów naraz, rozpocznie podział na ziarnistość wygodną dla sieci, a nie dla ciebie i musisz sobie z tym poradzić.

Powiązane problemy