c ++ читает неизвестное количество данных из сокета

Я написал простую tcp/ip соединение client-server в c++,

Это часть сервера, которая обрабатывает соединение

int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n = 0;

sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
cout << "Error opening socket" << endl;
exit(1);
}

bzero((char*)&serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if(bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr))<0){
cout << "Error binding" << endl;
exit(1);
}

listen(sockfd,1);
clilen = sizeof(cli_addr);

newsockfd = accept(sockfd,(struct  sockaddr *)&cli_addr, &clilen );

if(newsockfd < 0){
cout << "Error accepting" << endl;
exit(1);
}

bzero(bytes,size_tot);
uint64_t total_bytes_read = 0;
uint64_t total_bytes_to_read = size_tot;
while(total_bytes_read < total_bytes_to_read){
int bytes_read = read(newsockfd,bytes + total_bytes_read,total_bytes_to_read - total_bytes_read);
if(bytes_read == -1){
cout << "error reading "<< endl;
n = -1;
break;
}
total_bytes_read += bytes_read;
}

но это работает, если я знаю общее количество байтов для чтения. Что делать, если общее количество данных для чтения неизвестно? Как я могу изменить этот кусок кода?

1

Решение

Вы спросили, как исправить ваш низкоуровневый код приема. Это просто — просто позвоните read один раз и не используйте while петля. Призыв к read вернется, как только будет прочитан хотя бы один байт данных. Чтобы прочитать количество байтов, просто передайте размер вашего буфера (или оставшееся в нем пространство, если в нем уже есть какой-то остаток от предыдущего вызова).

Вам также понадобится код протокола высокого уровня, так же как и вы, если знаете количество байтов. Этот код, вероятно, должен быть немного другим. Если кусок байтов, который вы получили, включает в себя индикацию остановки, обработайте все байты до индикации остановки и сохраните лишние в буфере для следующего раза. Если нет, просто позвоните read снова и получить кучу больше байтов.

Ваш код обработки протокола должен выглядеть примерно так:

  1. Вызов read и добавьте сколько угодно байтов в буфер. (Обработка ошибки или нормального закрытия здесь.)
  2. Если данные в буфере не содержат указание остановки, перейдите к шагу 1.
  3. Обработка всех байтов до индикации остановки.
  4. Удалите обработанные байты из буфера, оставив необработанные байты.
  5. Переходите к шагу 2.

Кроме того, код, который вы дали в вопросе, будет вращаться вечно, если другая сторона закроет соединение. В этом случае, read вернет ноль, и вы никогда не сможете прочитать больше данных из соединения. Вы должны выйти из цикла, если read возвращает ноль.

3

Другие решения

Прежде всего, избавиться от всего bzero звонки. Я не знаю, почему это продолжает проникать в код хороших людей. Для этого есть ноль, нада, ничто не нужно.

Во-вторых, вам нужно либо как-то заранее сообщить размер передачи — например, HTTP 1.1 предоставляет эту информацию в заголовке — либо просто заявить, что соединение закрыто после того, как все данные были переданы — это будет HTTP 1.0 модель.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector