Как исправить слияние нескольких сегментов TCP в один? - PullRequest
0 голосов
/ 24 марта 2019

У меня есть два сверстника: Алиса и Боб.Боб пытается отправить Алисе список известных ему пиров.

Сначала Боб сообщает Алисе, сколько у него пиров, затем отправляет n строки с информацией об пирах Алисе.

Вот код для Боба:

if ((send(socket_fd, &(int){ 1 }, sizeof(int), 0)) == -1) { perror("Failed to send"); }
sleep(1); // Give him time to process the rqst

send(socket_fd, &peer_cnt, sizeof(peer_cnt), 0); 
for (int i = 0; i < peer_cnt; ++i) {
    char *peer_str = get_string(&peers[i]);
    printf("Send peer\t:\t%s\n", peer_str);
    send(socket_fd, peer_str, strlen(peer_str), 0); 
    free(peer_str);
}   

Вот код для Алисы:

char buf[128] = { 0 };
int n = 0;
recv(peer_sock_fd, &n, sizeof(n), 0);
printf("Number of incoming peers:\t%d\n", n); 

for (int i = 0; i < n; ++i) {
    memset(buf, '\0', sizeof(buf));
    recv(peer_sock_fd, buf, sizeof(buf), 0); 
    puts(buf);
}

Пример.Если Боб отправляет строки Алисы 2, существуют два случая.Во-первых, Алиса получает их отдельно (как я и предполагал), например, в этом случае вывод Алисы может быть george:127.0.0.1:5555: и michael:127.0.0.1:4444:.Во-вторых, Алиса получает их как одну строку, например george:127.0.0.1:5555:michael:127.0.0.1:4444:

Почему входящие строки иногда объединяются?

1 Ответ

2 голосов
/ 24 марта 2019

TCP - это потоковый протокол, и когда вы вызываете send (), он помещает ваши сообщения в специальный буфер один за другим, а затем отправляет их.Поскольку вы вызываете несколько системных вызовов send () за очень короткий промежуток времени, многие из них помещаются в один и тот же буфер и отправляются как одно сообщение.Иногда они отправляются отдельно, а иногда объединяются, иногда отправляется только половина сообщения, по умолчанию используется потоковый протокол.Что вы должны сделать (и именно так реализована каждая приличная программа TCP) - это разделить ваши сообщения.Лучший способ - использовать целое число сообщений в качестве первых 4 байтов каждого сообщения, а затем разделять сообщения в соответствии с их размерами.Я рекомендую вам прочитать руководство Биджа по сокетам (https://beej.us/guide/bgnet/html/multi/index.html). Оно объясняет эту концепцию и многое другое. Очень дружелюбный для новичков

...