风吹过


以前,晚餐后在学校田径场的大榕树下,散散步吹吹风,累了就去图书馆看看书,感觉真好。


27 GroupSock概述(一)——live555源码阅读(四)网络

[TOC] 博客园文章地址 http://www.cnblogs.com/oloroso/archive/2015/07/01/4613329.html

27 GroupSock概述(一)——live555源码阅读(四)网络

本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso
本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso

简介

group是组/群的意思,socket是网络接口的代名词了。这个部分很庞大,主要是与网络相关的。而live555的网络模块很多都涉及到组播的概念。
作为一个跨平台的流媒体服务库,live555对网络的封装很全面,值得一看。

1.网络通用数据类型定义

因为live555跨平台的特点,需要定义一些在数据类型来适应各个平台环境。
这写代码在live555sourcecontrol\groupsock\include\NetCommon.h文件中

#if defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE)
/* Windows */
#if defined(WINNT) || defined(_WINNT) || defined(BORLANDC) || defined(MINGW32) || defined(_WIN32_WCE)
#define MSWSOCK
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <windows.h>
#include <string.h>

#define closeSocket closesocket //关闭socket函数 #define EWOULDBLOCK WSAEWOULDBLOCK //10035L 可能会被阻塞 #define EINPROGRESS WSAEWOULDBLOCK //10035L 操作正在进行 #define EAGAIN WSAEWOULDBLOCK //10035L 再试一次 #define EINTR WSAEINTR //10004L 中断

#if defined(_WIN32_WCE) #define NO_STRSTREAM 1 #endif

/* Definitions of size-specific types: 定义特定大小的类型*/ typedef __int64 int64_t; typedef unsigned __int64 u_int64_t; typedef unsigned u_int32_t; typedef unsigned short u_int16_t; typedef unsigned char u_int8_t; // For “uintptr_t” and “intptr_t”, we assume that if they’re not already defined, then this must be // “uintptr_t”和“intptr_t”,我们认为如果他们不是已经定义,那么这一定是 // an old, 32-bit version of Windows: 一个老的,32位版本的Windows: #if !defined(_MSC_STDINTH) && !defined(_UINTPTR_T_DEFINED) && !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T) typedef unsigned uintptr_t; #endif #if !defined(_MSC_STDINTH) && !defined(_INTPTR_T_DEFINED) && !defined(_INTPTR_T_DECLARED) && !defined(_INTPTR_T) typedef int intptr_t; #endif

#elif defined(VXWORKS) /* VxWorks */ #include <time.h> #include <timers.h> #include <sys/times.h> #include <sockLib.h> #include <hostLib.h> #include <resolvLib.h> #include <ioLib.h>

typedef unsigned int u_int32_t; typedef unsigned short u_int16_t; typedef unsigned char u_int8_t;

#else /* Unix */ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <strings.h> #include <ctype.h> #include <stdint.h> #if defined(_QNX4) #include <sys/select.h> #include <unix.h> #endif

#define closeSocket close

#ifdef SOLARIS #define u_int64_t uint64_t #define u_int32_t uint32_t #define u_int16_t uint16_t #define u_int8_t uint8_t #endif #endif

#ifndef SOCKLEN_T #define SOCKLEN_T int #endif

2.Tunnel隧道封装

这里代码里面已经注释得很明白了。这个首先需要了解以下什么是Tunnel(隧道)。(简单的说,它就像是披着羊皮的狼)

tunnel中文译为隧道。网络隧道(Tunnelling)技术是个关键技术。网络隧道技术指的是利用一种网络协议来传输另一种网络协议,它主要利用网络隧道协议来实现这种功能。网络隧道技术涉及了三种网络协议,即网络隧道协议、隧道协议下面的承载协议和隧道协议所承载的被承载协议。

这里实现的TunnelEncapsulationTrailer类是一个很特殊的类,它不应该被用来创建对象。
对于这一部分,这里先不多说,先看后面的。
其定义在live555sourcecontrol\groupsock\include\TunnelEncaps.hh文件中

typedef u_int16_t Cookie;
/* cookie(储存在用户本地终端上的数据)
Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而
储存在用户本地终端上的数据(通常经过加密)。定义于RFC2109和2965都已废弃,最新规范是RFC6265 。
*/

/*tunnel中文译为隧道。网络隧道(Tunnelling)技术是个关键技术。网络隧道技术指的是利用一种网络协议来传输另一种网络协议,它主要利用网络隧道协议来实现这种功能。网络隧道技术涉及了三种网络协议,即网络隧道协议、隧道协议下面的承载协议和隧道协议所承载的被承载协议。 */

// 这个类很有意思,它内部并无数据成员,其函数成员的返回都是以this为基准进行偏移 // 后,转换这个偏移后的地址为相应的指针类型,再取指针指向内存的内容。 // 所以这个类并不会用来创建对象,而是作为一种类型来使用。可能诸如以下代码 // unsigned long long t= 0x1239874560864216L; // cout << ((TunnelEncapsulationTrailer*)&t)->address() << endl; // cout << 0x12398745 << endl;

class TunnelEncapsulationTrailer { // The trailer is layed out as follows: // bytes 0-1: source ‘cookie’ 源Cookie // bytes 2-3: destination ‘cookie’ 目的Cookie // bytes 4-7: address 地址 // bytes 8-9: port 端口 // byte 10: ttl TTL // byte 11: command 命令

    // Optionally, there may also be a 4-byte 'auxilliary address'
    // 随意,也可能有一个4字节的"辅助地址"
    // (e.g., for 'source-specific multicast' preceding this)
    // (例如,&ldquo;特定源组播&rdquo;在此之前)
    // bytes -4 through -1: auxilliary address
    // -4到-1字节(this之前4个字节),辅助地址

public:
Cookie&amp; srcCookie()
    { return *(Cookie*)byteOffset(0); }
Cookie&amp; dstCookie()
    { return *(Cookie*)byteOffset(2); }
u_int32_t&amp; address()
    { return *(u_int32_t*)byteOffset(4); }
Port&amp; port()
    { return *(Port*)byteOffset(8); }
u_int8_t&amp; ttl()
    { return *(u_int8_t*)byteOffset(10); }
u_int8_t&amp; command()
    { return *(u_int8_t*)byteOffset(11); }

    u_int32_t&amp; auxAddress()
            { return *(u_int32_t*)byteOffset(-4); }

private:    
//取this偏移charIndex
inline char* byteOffset(int charIndex)
    { return ((char*)this) + charIndex; }

};

const unsigned TunnelEncapsulationTrailerSize = 12; // bytes隧道封装拖车尺寸 const unsigned TunnelEncapsulationTrailerAuxSize = 4; // bytes辅助的尺寸 const unsigned TunnelEncapsulationTrailerMaxSize //最大尺寸 = TunnelEncapsulationTrailerSize + TunnelEncapsulationTrailerAuxSize;

// Command codes:命令码 // 0: unused const u_int8_t TunnelDataCmd = 1; //隧道的数据命令 const u_int8_t TunnelJoinGroupCmd = 2; //隧道连接组命令 const u_int8_t TunnelLeaveGroupCmd = 3; //隧道离开组命令 const u_int8_t TunnelTearDownCmd = 4; //隧道拆除命令 const u_int8_t TunnelProbeCmd = 5; //隧道探针命令 const u_int8_t TunnelProbeAckCmd = 6; //隧道探针ACK命令 const u_int8_t TunnelProbeNackCmd = 7; //隧道探针NACK命令 const u_int8_t TunnelJoinRTPGroupCmd = 8; //隧道加入RTP组命令 const u_int8_t TunnelLeaveRTPGroupCmd = 9; //隧道离开RTP组命令

// 0x0A through 0x10: currently unused.0x0a到0x10:目前未使用 // a flag, not a cmd code一个标识,不是命令码。隧道扩展标识 const u_int8_t TunnelExtensionFlag = 0x80; //bits:1000 0000

const u_int8_t TunnelDataAuxCmd //隧道数据辅助命令 = (TunnelExtensionFlag|TunnelDataCmd); const u_int8_t TunnelJoinGroupAuxCmd //隧道连接组辅助命令 = (TunnelExtensionFlag|TunnelJoinGroupCmd); const u_int8_t TunnelLeaveGroupAuxCmd //隧道离开组辅助命令 = (TunnelExtensionFlag|TunnelLeaveGroupCmd); // Note: the TearDown, Probe, ProbeAck, ProbeNack cmds have no Aux version // 注意:TearDown(拆除),Probe(探针),ProbeAck(Ack探针),ProbeNack(NACK探针)没有辅助版命令 // 0x84 through 0x87: currently unused. const u_int8_t TunnelJoinRTPGroupAuxCmd //隧道加入RTP组辅助命令 = (TunnelExtensionFlag|TunnelJoinRTPGroupCmd); const u_int8_t TunnelLeaveRTPGroupAuxCmd//隧道离开RTP组辅助命令 = (TunnelExtensionFlag|TunnelLeaveRTPGroupCmd); // 0x8A through 0xFF: currently unused //判断参数cmd是否是辅助命令 inline Boolean TunnelIsAuxCmd(u_int8_t cmd) { return (cmd&TunnelExtensionFlag) != 0; }