开发者

How read the TCP packet of a stream using a socket in C?

let me first tell what I am trying to do. I am trying to write a very simple proxy server. I used the socket API to create a socket. socket = so开发者_JS百科cket(AF_INET, SOCK_STREAM, 0));

my proxy server worked fine until I tried it for a streaming data. So what I did was my server socket listened to the requests and parsed them and then forwarded them to the actual server, I then used the read() call to read the packet & I blindly forward it back to the client.

For all html pages and images it works fine. but when I try to forward a streaming video I am not able to do it.

My socket always returns the application layer data (HTTP packet) but in a streaming video only the first packet is http and rest all are just TCP packets. So I am able to forward only the first HTTP packet. When I try to read the other packets which contain data (which are all TCP) I don't get anything at the application layer (which is obvious as there is nothing at application layer in those packets ). So I am stuck and I do not know how to read those packets from TCP layer (I dont wanna use raw socket) and get my job done.

thanks in advance


You have to parse the packet header to know how much data to read from the socket. at first, use a ring buffer (a circular one!) for example the BSD sys/queue.h to order the received data from the stream.

The code below shows how to extract header_length, total_length, source and destination Address of an IPv4 packet in layer 3. refer to IPv4 packet layout to understand offsets:


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



If you use the socket API, then you are on the layer below HTTP, that is, to you everything is "just TCP". If the connection is stuck somewhere, it is most likely that something else is broken. Note there is no guarantee that the HTTP request or reply header will even fit in a single packet; they just usually do.

An HTTP 1.1 compliant streaming server will use "Content-Encoding: chunked" and report the length of each chunk rather than the length of the entire file, you should keep that in mind when proxying.


So what I did was my server socket listened to the requests and parsed them

Why? An HTTP proxy doesn't have to parse anything except the first line of the request, to know where to make the upstream connection to. Everything else is just copying bytes in both directions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜