Получите полезные данные TCP от сокета немедленно (пакет за пакетом) в C - PullRequest
3 голосов
/ 15 сентября 2011

Как я могу получать данные (поток байтов) из открытого сетевого сокета в C для каждого пакета отдельно?Я хочу читать данные из сокета НЕМЕДЛЕННО по мере его поступления (как только пакет поступает на компьютер).

Кажется, когда я выполняю вызов read () (или recv ()) для сокета,Я получаю все TCP сообщение размером более 10 000 байт.Скорее, я хотел бы получить первый полезный груз сегмента TCP, обработать его, затем перейти к следующему и т. Д.

Примечание. Мне не нужны необработанные пакеты.Только полезная нагрузка данных сегмента TCP.

Также обратите внимание: в сущности, я хочу минимизировать задержку, обрабатывая данные сразу по мере их поступления, в отличие от ожидания накопления всего сообщения TCP на уровне TCP.

Любые идеи будут высоко оценены, спасибо!

Ответы [ 4 ]

2 голосов
/ 15 сентября 2011

Может быть, я неправильно понимаю ваш вопрос (например, я не могу понять, «не хочу, чтобы сырые пакеты были только полезными данными TCP»), но подключен простой необработанный сокет (IPPROTO_TCP), а затем прослушан с помощью recv ()сделаю работу.Вы указываете максимальный размер буфера в качестве аргумента в recv (), но когда приходит загрузка TCP, об этом будет сообщено обратно - не дожидаясь заполнения буфера.Вот фрагмент кода, который печатает TCP-пакеты:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include // your header to print out bytes and error messages here

int main(void) {
    int i, recv_length, sockfd;
    u_char buffer[9000];

    if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
        // your error message here

    for(i=0; i < 3; i++) {
        recv_length = recv(sockfd, buffer, 8000, 0);
        printf("Got a %d byte packet\n", recv_length);
        // your routine to print out bytes here
    }
}

Если это не то, что вас беспокоило, пожалуйста, уточните.

Редактировать: Из того, что я слышу и читаю, используяБиблиотека pcap (libcap) превосходит использование необработанных сокетов (более надежная; очень мощная - написана парнями, написавшими tcpdump).Тем не менее, я все еще изучаю pcap и до сих пор изо всех сил пытаюсь заставить его работать должным образом с беспроводными устройствами.Но, возможно, посмотрите на это тоже, если вам это нужно на постоянной основе.

1 голос
/ 15 сентября 2011

TCP не имеет "сообщений". Это просто поток байтов. API сокетов не дает вам доступа к данным, переносимым отдельными IP-пакетами или сегментами TCP.

Однако, если вы хотите прочитать данные, как только операционная система может предоставить вам некоторые данные, вы

  1. Установите сокет в неблокирующий режим с помощью вызова fcntl () дескриптора сокета.
  2. Зарегистрируйте дескриптор сокета с помощью службы уведомлений ввода / вывода, такой как select (), poll (), epoll.
  3. Ожидание событий ввода-вывода для этой службы.
  4. Когда указано, что сокет готов к чтению, вы читаете с него - и вы получите столько данных, которые доступны в то время (и обработаете случай, когда read / recv возвращает -1, а errno установлено в EWOULDBLOCK)
0 голосов
/ 15 сентября 2011

По сути, я хочу минимизировать задержку, обрабатывая данные сразу же по мере их поступления,

Существует задержка планирования между временем, когда данные становятся доступными в буфере сокета ядра, и временем, когда процесс получения активируется из блокировки read() / recv() / select() / epoll() / и т. Д. , С немодифицированным ядром Linux и процессом в реальном времени это не менее 4 микросекунд.

Если вы хотите избежать задержки при планировании, можно выбрать опрос / ожидание, не позволяющие ОС перевести процесс в спящий режим. То есть, вызов select() с таймаутом 0 или вызов recv() в неблокирующем сокете и немедленная повторная попытка вызова, если он вернет EAGAIN. Очевидно, что это должен быть процесс FIFO реального времени, который не подчиняется временным интервалам планировщика, иначе он исчерпает свой занятый период ожидания и будет усыплен.

в отличие от ожидания накопления всего TCP-сообщения на уровне TCP.

Чтобы быть педантичным, не существует такой вещи, как TCP-сообщение . TCP доставляет данные, как только они поступают, при условии, что они поступили в порядке.

0 голосов
/ 15 сентября 2011

Вы должны получать данные, как только они поступят.Не существует такого понятия, как «полное TCP-сообщение».Каждый вызов read или recv должен давать вам столько байтов в порядке, сколько было получено в то время.

...