2012-10-20 26 views
10

C++ ma następującą funkcję do odbierania bajtów z gniazda, może sprawdzić liczbę bajtów dostępnych z flagą MSG_PEEK. Z MSG_PEEK, zwracana wartość „recv” jest liczba bajtów dostępnych w gnieździe:Uzyskaj liczbę bajtów dostępnych w gnieździe przez "recv" z "MSG_PEEK" w C++

#include <sys/socket.h> 
ssize_t recv(int socket, void *buffer, size_t length, int flags); 

Potrzebuję uzyskać liczbę bajtów dostępnych w gnieździe bez tworzenia buffer (bez przydzielania pamięci dla buffer). Czy to możliwe i jak?

Odpowiedz

25

Poszukujesz: ioctl(fd,FIONREAD,&bytes_available) i pod Windows ioctlsocket(socket,FIONREAD,&bytes_available).

Należy pamiętać, że system operacyjny niekoniecznie gwarantuje ilość buforowanych danych, więc jeśli czekasz na bardzo dużo danych, lepiej będzie odczytać dane w miarę ich dostarczania i przechowywania. w swoim własnym buforze, dopóki nie będziesz mieć wszystkiego, czego potrzebujesz do przetworzenia czegoś.

Aby to zrobić, co jest zwykle wykonywane jest po prostu czytać kawałki na raz, takie jak

char buf[4096]; 
ssize_t bytes_read; 
do { 
    bytes_read = recv(socket, buf, sizeof(buf), 0); 
    if (bytes_read > 0) { 
     /* do something with buf, such as append it to a larger buffer or 
      * process it */ 
    } 
} while (bytes_read > 0); 

A jeśli nie chcesz siedzieć tam czeka na dane, należy spojrzeć na select lub epoll, aby określić, kiedy dane są gotowe do odczytania, a flaga O_NONBLOCK dla gniazd jest bardzo przydatna, jeśli chcesz mieć pewność, że nigdy nie blokujesz recv.

+0

przychodzące dane do gniazda mają być "ciągłym strumieniem bajtów" lub "serią pakietów tcp"? – jondinham

+0

Zerkanie z maksymalną liczbą bajtów (obsługiwane przez program) sprawi, że podwójne zadanie myślę, bo kiedy faktycznie zajmujemy się danymi, czytamy po raz drugi – jondinham

+1

Prawidłowo, dlatego pierwsza metoda jest lepsza, chociaż chyba działasz z szybkością Gb/s, wtedy nigdy tego nie zauważysz. – hexist

1

W systemie Windows można użyć funkcji ioctlsocket() z flagą FIONREAD, aby zapytać gniazdo, ile bajtów jest dostępnych, bez konieczności odczytywania/przeglądania samych bajtów. Zwrócona wartość to minimalna liczba bajtów recv() może zostać zwrócona bez blokowania. Zanim zadzwonisz na numer recv(), może przybyć więcej bajtów.

+0

Jestem na centos linux – jondinham

+2

@PaulDinh Działa również na Linux i Unix za pośrednictwem ioctl(). – EJP

+0

Ta odpowiedź jest błędna. W dokumentacji jest całkiem jasne, że 'FIONREAD', w systemie Windows, * nie * zwraca liczbę bajtów, które są dostępne z' recv' bez blokowania. W systemie Windows 'recv' może pobierać dane z niższych warstw (takich jak filtry i kolejki z własnymi buforami), natomiast' FIONREAD' nie robi tego i sprawdza tylko górną warstwę. Zobacz [element 12] (https://tangentsoft.net/wskfaq/articles/lame-list.html). –