如何读取使用在C座流的TCP数据包?

问题描述 投票:1回答:3

让我先告诉我想做的事情。我想写一个非常简单的代理服务器。我使用的套接字API创建套接字。 socket = socket(AF_INET, SOCK_STREAM, 0));

我的代理服务器,直到我尝试了一个数据流的罚款。所以我所做的就是我的服务器套接字听取了请求,并分析它们,然后将它们转发到实际的服务器,然后我用read()调用来读取数据包和我盲目地将其转发回客户端。

对于所有的HTML页面和图像,它工作正常。但是当我尝试着一个视频流,我无法做到这一点。

我的插座始终返回应用层数据(HTTP数据包),但在视频流只有第一个包是http和休息都只是TCP数据包。所以,我能只转发第一个HTTP数据包。当我尝试读取一个包含数据(这些都是TCP)的其他数据包我不明白在应用层东西(这是显而易见的,因为其中没有在这些数据包应用层)。所以我坚持,我不知道如何读从TCP层(我不想用原始套接字),这些数据包,并让我的工作做好。

提前致谢

sockets proxy tcp stream
3个回答
0
投票

如果您使用socket API,那么你是在HTTP层上,也就是你的一切“只是TCP”。如果连接某个地方卡住了,这是最有可能是别的东西坏了。注意也不能保证该HTTP请求或应答标题将即使配合在单个数据包中;他们只是通常做。

一个HTTP 1.1兼容的流媒体服务器将使用“内容编码:分块”,并报告每个块的长度,而不是整个文件的长度,你应该进行代理时,记住这一点。


0
投票

所以我所做的就是我的服务器套接字听取了请求,并解析它们

为什么? HTTP代理不必解析任何东西,除了请求的第一线,知道在哪里,使上游连接。其他的一切只是复制在两个方向字节。


0
投票

你必须解析报文头知道有多少数据从套接字读取。起初,使用例如环形缓冲区(圆形一个!)的BSD sys/queue.h从流命令接收到的数据。

下面的代码显示如何提取IPv4分组的header_lengthtotal_length,源和目的地地址在层3是指IPv4 packet layout理解偏移:


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;
}


© www.soinside.com 2019 - 2024. All rights reserved.