Как читать TCP-пакет потока, используя сокет в C? - PullRequest
1 голос
/ 11 февраля 2011

позвольте мне сначала рассказать, что я пытаюсь сделать. Я пытаюсь написать очень простой прокси-сервер. Я использовал сокет API для создания сокета. socket = socket(AF_INET, SOCK_STREAM, 0));

мой прокси-сервер работал нормально, пока я не попробовал потоковую передачу данных. Итак, что я сделал, так это то, что мой серверный сокет прослушал запросы и проанализировал их, а затем направил их на реальный сервер, затем я использовал вызов read () для чтения пакета и вслепую переадресовал его обратно клиенту.

Для всех html-страниц и изображений все работает нормально. но когда я пытаюсь переслать потоковое видео, я не могу это сделать.

Мой сокет всегда возвращает данные прикладного уровня (HTTP-пакет), но в потоковом видео только первый пакет является http, а остальные - просто TCP-пакетами. Поэтому я могу пересылать только первый HTTP-пакет. Когда я пытаюсь прочитать другие пакеты, которые содержат данные (которые все являются TCP), я не получаю ничего на уровне приложений (что очевидно, поскольку на уровне приложений в этих пакетах ничего нет). Так что я застрял и не знаю, как читать эти пакеты со слоя TCP (я не хочу использовать необработанный сокет) и выполнять свою работу.

заранее спасибо

Ответы [ 3 ]

0 голосов
/ 14 февраля 2011

Итак, что я сделал, так это то, что мой серверный сокет слушал запросы и анализировал их

Почему?HTTP-прокси не нужно анализировать что-либо, кроме первой строки запроса, чтобы узнать, где установить восходящее соединение.Все остальное - просто копирование байтов в обоих направлениях.

0 голосов
/ 04 февраля 2019

Вы должны проанализировать заголовок пакета, чтобы узнать, сколько данных нужно прочитать из сокета. сначала используйте кольцевой буфер (круговой!), например, BSD sys/queue.h, чтобы упорядочить полученные данные из потока.

В приведенном ниже коде показано, как извлечь header_length, total_length, адрес источника и назначения пакета IPv4 на уровне 3. См. Схема пакета IPv4 , чтобы понять смещения:


typedef struct {
    unsigned char version;
    unsigned char header_length;
    unsigned short total_length;
    struct in_addr src;
    struct in_addr dst;
} Packet;


int rb_packet_write_out(RingBuffer *b, int fd, int count) {
    int i;
    for (i = 0; i < count; i++) {
        if (b->level < 20) {
            return i;
        }
        Packet p;
        unsigned char *start = b->blob + b->read_cursor;
        unsigned char b1 = start[0];
        p.version = b1 >> 4;
        p.header_length = b1 & 0xf;
        p.total_length = bigendian_deserialize_uint16(start + 2);
        if (b->level < p.total_length) {
            return i;
        }

        memcpy(&(p.src), start + 12, 4);
        memcpy(&(p.dst), start + 16, 4);

        char s[5], d[5];
        inet_ntop(AF_INET, &(p.src), s, INET_ADDRSTRLEN);
        inet_ntop(AF_INET, &(p.dst), d, INET_ADDRSTRLEN);

        L_DEBUG("Packet: v%u %s -> %s (%u)", p.version, s, d, p.total_length);
    }
    return i;
}


0 голосов
/ 11 февраля 2011

Если вы используете API сокетов, то вы находитесь на уровне ниже HTTP, то есть для вас все "просто TCP".Если соединение где-то застряло, скорее всего, что-то еще нарушено.Обратите внимание, что нет гарантии, что HTTP-запрос или заголовок ответа даже поместятся в одном пакете;они обычно это делают.

Потоковый сервер, совместимый с HTTP 1.1, будет использовать «Content-Encoding: chunked» и сообщать о длине каждого чанка, а не о длине всего файла, об этом следует помнить при прокси.

...