2017-01-01 6 views
0

Я создал сервер и клиент с c в Mac OS.
Что они делают, просто: сервер отправляет сообщения, и клиент их получает.
Однако я не знаю, почему, но я всегда теряю некоторые сообщения, когда я печатаю более одного сообщения с помощью scanf.
Вот основные коды:
socket TCP: Почему я теряю сообщения с помощью scanf

// client 
char msg[200]; 
while(1) 
{ 
    if(read(sockclient, msg, sizeof(msg)) <= 0) 
    { 
     break; 
    } 
    printf("Message recu: %s\n", msg); 
    bzero(msg, 200); 
} 


// server 
while(1) 
{ 
    lg=sizeof(coord_client); 
    newsockfd=accept(sockserveur,(struct sockaddr*)&coord_client,(socklen_t *)&lg); 
    char msg2[100]; 
    while(1) 
    { 
     scanf("%s",msg2); 
     write(newsockfd,msg2,sizeof(msg2)); 
     printf("message envoye\n"); 
     bzero(msg2, sizeof(msg2)); 
    } 
} 


Проблема: если я типа сообщения по одному, например, a<Enter>, b<Enter>, все в порядке. Но если я наберу несколько сообщений за один раз, я всегда потеряю некоторые из них. Например, если я набираю a b c d<Enter>, что означает, что я хочу отправить четыре сообщения: a, b, c и d, клиент всегда может получить три из них, c пропущен. Но сервер отправляет четыре раза, потому что я получаю четыре message envoye.

EDIT
Я проверил возвращаемое значение функции read и я получаю то, что я не понимаю. enter image description here

Обратите внимание: когда read возвращается 200 вместо 100, клиент потеряет следующее сообщение.

+1

Какой размер 'BUF'? у вас есть 100 с одной стороны и «BUF» с другой стороны. –

+2

Вы должны проверить возвращаемое значение 'read()'. Он может не вернуть весь размер сообщения, он может вернуться меньше, чем вы указываете. – Barmar

+0

также не нужно посылать весь буфер: 'strlen (msg2) + 1' будет достаточно, чтобы отправить строку + завершение –

ответ

3

Ну, вы просто читаете 200 байт, но пишете 100 байт. Иногда перед записью клиента есть две записи. Поэтому он читает два сообщения подряд.

char msg[101]; 
size_t i = 0; 
ssize_t ret; 
while (i < 100 && (ret = read(sockclient, msg + i, sizeof msg - i - 1)) <= 0) 
{ 
    i += (size_t)ret; 
} 
if (i == 100) { 
    msg[100] = '\0'; 
    printf("Message recu: %s\n", msg); 
} 
+0

'i <100' должно быть' i <99', не так ли? – alk

+0

@alk Нет, потому что сервер пишет 100 байт, а 'i' должен представлять, сколько байтов мы читаем. Я не тестировал: p. – Stargateur

+0

Вам нужно сохранить пространство для '0'-терминатора. Таким образом, буфер полезной нагрузки фактически имеет размер буфера -1. – alk