recv будет заблокирован, если в потоке нет данных. Любые данные, извлеченные из потока, длина возвращается из recv. Вы можете написать простую функцию для извлечения полных данных, просто используя переменную смещения и проверяя возвращаемое значение.
Подойдет такая простая функция.
ssize_t readfull(int descriptor,char* buffer, ssize_t sizetoread){
ssize_t offset = 0;
while (offset <sizetoread) {
ssize_t read = recv(descriptor,buffer+offset,sizetoread-offset,0);
if(read < 1){
return offset;
}
offset+=read;
}
return offset;
}
Также серверы обычно отправляют своего рода EOF, когда данные закончены. Либо сервер может сначала отправить длину сообщения для чтения, которая имеет постоянный размер, четыре или восемь байтов, а затем он отправит данные, чтобы вы заранее знали, сколько читать. Или, например, в случае HTTP, есть поле длины содержимого, а также разделители '\ r \ n'.
На самом деле нет способа узнать, сколько данных доступно серверу отправить вам, это непрактично. Сервер должен сообщить вам, сколько данных есть, через какой-то индикатор.
Поскольку вы пишете сервер самостоятельно, вы можете сначала отправить четырехбайтовое сообщение, которое может быть значением int, указывающим, сколько данных клиент должен прочитать.
Итак, ваш сервер может выглядеть так:
int sizetosend = arbitrarysize;
send(descriptor,(char*)&sizetosend,sizeof(int),0);
send(descriptor,buffer,sizetosend,0);
Затем на стороне клиента прочтите четыре байта, затем буфер.
int sizetoread = 0;
ssize_t read = recv(descriptor,(char*)&sizetoread,sizeof(int),0);
if(read < 4)
return;
//Now just follow the code I posted above