Male pytanie odnosnie winsock & recv

Odpowiedz Nowy wątek
2011-09-08 21:13
0

Witam. Napisalem maly program analizujacy wiadomosci na irc, nie jest to spamer. Pomaga mi wyszuac ludzi o odpowiednich kryteriach. Wszystko dziala prawie dobrze... Od czasu do czasu wystepuje blad, tak jakby 2 wiadomosci lacza sie w 1 i sa odebrane na raz co powoduje bug'a. Tu moje pytanie czy moge w ten sposob uzyc funkcji recv?

recv(sServ, buffer, 512, 0);

Nie wiem czy moge ustawic na sztywno dlugosc "buffer" - wyczytalem w RFC irc'a ze maxymalna dlugosc pakietu to 512, normalnie jest to okolo 100 czyli spora czesc jest nie uzywana. Czy to moze powodowac problem? Mysle tez o napisaniu funkcji ktora bedzie odbierala po znaku zanim nie napotka '\r', ale to ostatecznosc. Mam nadzieje ze nie namotalem, pozdro ;)


non omnis moriar i tyle :-)

Pozostało 580 znaków

2011-09-08 21:20
0

http://msdn.microsoft.com/en-[...]ry/ms740121%28v=vs.85%29.aspx
czyli Twoje recv, odczyta maksymalnie 512 bajtów, a ile dokładnie wczyta możesz sprawdzić tak:
int n =recv(sServ, buffer, 512, 0);

jeśli koniecznie musisz mieć 512 to możesz zrobić tak: (pisane z ręki więc mogą być błędy)

int br = 0; //ilosc bajtow odebranych
while (br!=512)
{
  int n = recv(sServ, buffer, 512-br, 0);
  br+=n;
}

ale bardziej polecam zrobić pętle odbierającą zawsze np te 512 bajtów, parsowanie odebranych danych i odbieranie danych dalej (w jakimś wątku najlepiej).

zastanów się co rozumiesz przez słowo pakiet, bo recv służy do odbierania danych, a pakiety z tych danych musisz sobie sam uformować.


░█░█░█░█░█░█░█░█░█░█░█░
edytowany 1x, ostatnio: krwq, 2011-09-08 21:24

Pozostało 580 znaków

2011-09-08 21:37
0

W programowaniu sieciowym jestem laik, wiem wiem ze pakiet powstaje po parsowaniu. Tak myslalem ze sie nie zrozumiemy ale sprobuje jeszcze raz ;p. Nie chodzi mi o to zeby koniecznie odebrac na raz te 512 bajtow, nawet tak nie chce. Chyba zle przedstawilem problem, probuje sie dowiedziec czy jezeli do recv() dam char buffer[512] to istnieje mozliwosc ze znajda sie w niej 2 male pakiety? Czy zawsze jest tak ze recv odbiera tylko jeden pakiet?


non omnis moriar i tyle :-)

Pozostało 580 znaków

2011-09-08 21:42
0

Dalej się nie rozumiemy. Co rozumiesz poprzez pakiet?
Generalnie obojętnie co odpowiesz na to pytanie, odpowiedź na Twoje brzmi: TAK, może odebrać więcej


░█░█░█░█░█░█░█░█░█░█░█░
edytowany 1x, ostatnio: krwq, 2011-09-08 21:42

Pozostało 580 znaków

2011-09-08 21:46
0

Przez pakiet rozumiem ciag znakow zakonczony \r\n. Enyłej, otrzymalem odpowiedz i wiem co jest do poprawki. Jednak bede musial odbierac po znaku... Dzieki za pomoc :)


non omnis moriar i tyle :-)

Pozostało 580 znaków

2011-09-08 22:03
0

nie musisz odbierać po znaku. Możesz zostawić tak jak jest, tylko np zrobić dwa bufory:

  1. na odbieranie (np. ten co juz masz 512bajtow)
  2. na parsowanie (ok. 3x większy od tego wyżej, zakładając że najdłuższa długość linii to 512bajtów)
    w drugim buforze zapisz sobie takie dane:
    początek
    koniec
    i wyjdź z założenia że początek nie zawsze musi być w tym buforze przed końcem, ponieważ do tego bufora powinieneś zapisywać w kółko: (pisane z reki)
    char buff[1536];
    char buff_odb[512];
    char* buff_end = buff+1536;
    char* pocz = buff;
    char* koniec = buff;
    while (!koniecprogramu)
    {
    int n = recv(sServ, buff_odb, 512, 0);
    if (koniec+n>buff_end)
    {
    int dokonca = (int)(buff_end-koniec);
    memcpy(koniec,buff_odb,dokonca);
    memcpy(buff,buff_odb+dokonca,n-dokonca);
    koniec = buff+n-dokonca;
    }
    else
    {
    memcpy(koniec,buff_odb,n);
    koniec+=n;
    }
    // parsowanie:
    char* p= pocz;
    while (p!=koniec)
    {
    // tutaj sobie sprawdzasz czy wystapil po kolei ciag \r\n i znak za miejscem tego wystapienia uystawiasz pocz = te_miejsce
    if (p==buff_end)
      p = buff;
    }
    }

░█░█░█░█░█░█░█░█░█░█░█░

Pozostało 580 znaków

2011-09-09 07:27
0

Dzis mam 6h lekcji na komputerze to przeanalizuje Twoj kod. Dzieki za zainteresowanie :)


non omnis moriar i tyle :-)

Pozostało 580 znaków

2011-09-09 08:53
Kumashiro
0
arasso12 napisał(a)

Przez pakiet rozumiem ciag znakow zakonczony \r\n. Enyłej, otrzymalem odpowiedz i wiem co jest do poprawki. Jednak bede musial odbierac po znaku... Dzieki za pomoc :)

Jesli chodzi o Winsock to jestem zielony. Jeśli zachowuje się on inaczej niż sockety POSIXowe, to będę pewnie plótł bzdury i można zignorować ten wpis

Funkcji recv() wisi i powiewa co jest w danych które otrzymuje. Dla niej '\r\n' nie jest żadną informacją o strukturze danych. Sam musisz się zatroszczyć o odpowiedni podział na pakiety tego, co recv() odbierze. Tak, w jednym wywołaniu recv() możesz otrzymać więcej niż jedną linię (dane zakończone '\r\n'). Tak, w jednym wywołaniu recv() możesz otrzymać tylko część linii (brak '\r\n'). Tak, w jednym wywołaniu recv() możesz otrzymać conajmniej jedną pełną linię i część innej. Poczytaj o protokołach strumieniowych, TCP itp.

Pozostało 580 znaków

2011-09-09 13:51
0

Racja, mialem mylne wyobrazenie pakietu...
@krwq dzieki za kod, ale moje rozwiazanie jest chyba prostsze. Jezeli zawiedzie to przejde do Twojej propozycji.

Wiec zakodzilem cos takiego:

 void serwer::odbierz(char buffer[512])
{
    //recv(sClient, buffer, DL_WIAD, 0);

    char c;
    int t=0;
    do
    {
        recv(sClient, &c, 1, 0);
        buffer[t]=c;
        t++;
    }
    while(c!='\n');

    buffer[t]=char(0);

}

Teraz faza testow, jak nie wysypie sie w godzinach szczytu bedzie super ;D. Dzieki za pomoc :)


non omnis moriar i tyle :-)
Wolne i nie zgodne z RFC. Separatorem jest '\r\n', a nie samo '\n'. - Kumashiro 2011-09-09 14:04

Pozostało 580 znaków

2011-09-09 14:02
0

to powinno działać, aczkolwiek możesz w pewnym momencie zacząć czuć, że to muli...
powinieneś jeszcze dodać jako ten ostatni parametr MSG_WAITALL,
sprawdzć czy funkcja zwróciła 1, jeśli nie to znaczy że wystąpił błąd lub połączenie zostało zamknięte


░█░█░█░█░█░█░█░█░█░█░█░
edytowany 1x, ostatnio: krwq, 2011-09-09 14:04

Pozostało 580 znaków

2011-09-09 14:07
0

Dzieki za rady :)

@Kumashiro
Wiem ze separatorem jest '\r\n' ... zrobilem tak bo jak bede odbieral znak po znaku az do napotkania '\r' pierwszy "pakiet" bedzie ok a nastepny bedzie sie skladal z '\r'... To samo zrobilem tylko az do napotkania '\n' - na poczatku kazdego kolejnego pakietu po pierwszym byl znak nowej linii.


non omnis moriar i tyle :-)
edytowany 1x, ostatnio: arasso12, 2011-09-09 14:13

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0