jam231 / sia

Stock market server (part of stock market simulation system).
1 stars 0 forks source link

Nasze nieprawdziwe zrozumienie TCP (chyba) #15

Closed kaiks closed 11 years ago

kaiks commented 11 years ago
[20:21] <@kx> w qt
[20:21] <@KrzaQ> nom
[20:21] <@kx> jak sa te sloty na tcp
[20:21] <@KrzaQ> nom
[20:21] <@kx> to jak jest otrzymywany odczyt
[20:21] <@kx> to te pakiety moga sie skleic?
[20:22] <@KrzaQ> y
[20:22] <@KrzaQ> tcp nie ma rozdzielenia pakietow
[20:22] <@kx> i one sa wszystkie otrzymywane w jednym buforze i potem pewnie nastepny event to juz calkiem nowa seria?
[20:22] <@KrzaQ> wiec twoj protokol musi w jakis sposob umiec je rozkleic
[20:22] <@KrzaQ> y
[20:22] <@kx> k

Ogólnie sprawa jest taka że z tego co widzę w naszym kodzie QT (i moim kodzie Ruby) discardujemy sobie fajnie reszte sklejonego pakietu licząc że będzie nowy signal na osobny pakiet. Trzeba zrobić tam pętle jakąś albo jakiś bufor własny. Ogólnie jakoś mądrzej to załatwić.

Jeśli mówię jakieś straszne głupoty to dajcie znać, ale u mnie w ruby log: Got data [**0, 16, 9, 1**, 0, 0, 0, 2, 0, 0, 3, -24, 0, 0, 16, 94, **0, 16, 9, 1**, 0, 0 , 0, 2, 0, 0, 3, -24, 0, 0, 16, 84] wskazuje na to, że tak jest, i nie widzę kodu w QT który by się przed tym bronił (ala https://gist.github.com/KrzaQ/305b3da8d9965cf06f82 )

marimarek commented 11 years ago

To o tym już pisałem, znaczy się ja pisałem o fragmentacji, bo ze sklejaniem, nie ma problemów w Qt, bo tam nic nie usuwamy, wyjmujemy tylko tyle ile potrzeba, a reszta zostaje w buforze(przynajmniej tak było, nie wiem czy coś się nie zmieniło).

kaiks commented 11 years ago

Nie no, problem właśnie jest taki, że nie zostaje w buforze, z tego co rozmawiałem i zaobserwowałem

marimarek commented 11 years ago

Ale my czytamy tylko z socket'a tyle bajtów ile ma dana wiadomość:

QDataStream message(m_socket->read(msgLength));

Reszta zostaje w sockecie.

P.S. Jakimi tagami sie kod oznacza?

kaiks commented 11 years ago

No to chyba właśnie taki nie działa. Dostajesz notyfikację na temat tego co było w sockecie i masz sobie to obsłużyć a jak nie to papa. Spróbuj posłać wiele pakietów jednocześnie i sprawdź zresztą, bo mi się to nie wzięło z nieba, tylko z praktyki. No chyba że masz jakieś alternatywne magiczne wyjaśnienie (i np. twierdzisz znajomy którego wypowiedź przytaczałem powyżej zrobił sobie bufor pośredni tak dla frajdy?)

składnia: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet

marimarek commented 11 years ago

Akurat dla mnie fora nie są wiarygodnym źródłem. A ludzie piszą tam często dziwne rzeczy. Z dokumentacji http://qt-project.org/doc/qt-4.8/qiodevice.html#read-2 nie wynika, żeby reszta danych była usuwana. A sygnał nie ma takiej nie ma takiej możliwości, ab y usunąć te dane(chyba, że będzie podłączony do niego slot, który te dane usunie).

kaiks commented 11 years ago

To nie jest z forum, tylko wypowiedź mojego znajomego, który, z tego co wiem, miał więcej styczności z TCP niż Ty. Twój link ma się nijak ma do slota, do którego połączona jest metoda readData: http://qt-project.org/doc/qt-4.8/qiodevice.html#readyRead

Nie wiem co rozumiesz przez to że sygnał nie ma możliwości.

PS: dasz rade zrobic te wizualizacje?

marimarek commented 11 years ago

Nie wiem co do wizualizacji, może w nocy nad ranem, w pracy jutro. Na chwilę obecną można to robić poprzez wywołanie w gnuplocie plot 'Scieżka do pliku', pliki z jakimiś tam wykresami tworzone są z poziomu bazy danych, po wywołaniu tego co Ci wysłałem. Tylko wtedy gnuplot tworzy same punkciki. Znaleźć polecenie, które je połączy linią na pewno jeszcze znajde, ale skryptu raczej nie napisze, który automatycznie wygeneruje te wykresy.

Co do temtu to TCP nie ma tu nic do rzeczy, bo ja się całkowicie zgadzam z tym co Ty/Twój kolega napisałeś odnośnie TCP. Kwestia jest taka, że moim zdaniem Qt buforuje te dane. A co do, że sygnał nie ma możliwości. To sygnał sam w sobie nic nie robi jedynie uruchamia sloty lub inne sygnały do niego podłączone. Więc albo dane musiałyby być usunięte z bufora przed wysłąniem sygnału(wtedy byśmy ich nie dostali) albo sygnał musiałby być podłącozny do slotu, który to robi(ale sloty są uruchamiane w kolejności w jakiej były podłączane, a myśmy podłączyli się na pewno do tego sygnału później niż zrobiłą to biblioteka) albo my sami musielibyśmy usuwać te dane w slocie, który mamy podłączony do sygnału, a my wywołujemy tam tylko funkcję read z tąd mój link.

EDIT: Twój cytat nie mówi nic po za tym, że ten sygnał nie zostanie wyemitowany dopóki nie przyjdą nowe dane i że dziedzicząc po tej klasie powinniśmy ten sygnał wysyłać tylko w takich watunkach.

Wydaje mi się, że możesz myśleć, że dane które dostajemy są do nas przesyłane przez sygnał? Tak nie jest sygnał nas tylko informuje, że do socketu doszły nowe dane, a odczytać musimy je z tamtąd sami i tak też robimy.

jam231 commented 11 years ago

Karol niestety dość nieprecyzyjnie się wyraził. W zdaniu "discardujemy sobie fajnie reszte sklejonego pakietu licząc że będzie nowy signal na osobny pakiet." slowko "discardujemy" jest dosc nieszczesliwe, bo rzeczywiscie tak jak Marek zauważył niczego nie usuwamy, ani nie odrzucamy (vide "discard"). Oczywiście Karol ma racje, że jest bug, który polega na tym, że gdy dostajemy sygnal my zakladamy w readData(), że w buforze jest tylko jedna wiadomosc i tylko jedna obslugujemy. Reszta pozostaje w buforze, co powoduje pewne opożniienia w wykonaniu zadań nadesłanych przez użytkownika który wysyła nam pakiety paczkami, a nie po jednym. Dodałem patcha.

kaiks commented 11 years ago

@jam231 Skoro już jesteś

    out << static_cast<qint16>(2*sizeof(qint8) + sizeof(qint16) + 3*sizeof(qint32))
        << static_cast<qint8>(type())
        << static_cast<qint8>(m_transactionType)
        << static_cast<qint32>(m_stockId)
        << static_cast<qint32>(m_amount)
        << static_cast<qint32>(m_price);

ładnie to tak? kolejne 40 minut straciłem :D możesz też przy okazji poprawić :p

to jest w order.cpp

I fakt, wytłumaczenie @jam231 co do pakietów jest sensowne. My bad.

kaiks commented 11 years ago

Juz sie wzialem i zrobilem.