37 网络相关函数(五)——live555源码阅读(四)网络
本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso
本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso
简介
网络相关函数是一系列用于操作网络数据的函数。在多个文件中都有相关的函数的定义。还有一些函数是系统socket API
相关函数,就不提了。
这一系列的函数大多有一个特点,需要一个UsageEnvironmet&型的参数。
这些方法大多在live555sourcecontrolgroupsockincludeGroupsockHelper.hh
中声明。
10)MAKE_SOCKADDR_IN构建sockaddr_in结构体宏
1 #ifdef HAVE_SOCKADDR_LEN 2 #define SET_SOCKADDR_SIN_LEN(var) var.sin_len = sizeof var 3 #else 4 #define SET_SOCKADDR_SIN_LEN(var) 5 #endif 6 7 // sockaddr_in var,使用adr和prt为其赋值(AF_INET) 8 #define MAKE_SOCKADDR_IN(var,adr,prt) /*adr,prt must be in network order*/ 9 struct sockaddr_in var; 10 var.sin_family = AF_INET; 11 var.sin_addr.s_addr = (adr); 12 var.sin_port = (prt); 13 SET_SOCKADDR_SIN_LEN(var);
11)setupDatagramSocket设置数据报套接口
setupDatagramSocket
函数有两个参数(UsageEnvironment& env, Port port)
。根据env
的groupsockPriv
成员来确定重用标识。如果groupsockPriv
为空则使用默认设置。
setupDatagramSocket
创建一个数据报形式的socket
套接口,如果端口port 0
的时候,不进行绑定(,且
ReceivingInterfaceAddrINADDR_ANYbind
)。否则若port==0
的时候,绑定ReceivingInterfaceAddr
(不为INADDR_ANY
)和端口0
(内核选择端口)。不为0
的时候绑定INADDR_ANY
(内核选择IP
)和端口port
。
绑定完成之后设置多播发生接口。如果全局的SendingInterfaceAddr== INADDR_ANY
则不设置。
函数成功返回一个socket
套接口句柄,失败返回-1
。
1 // 设置数据报套接字 2 int setupDatagramSocket(UsageEnvironment& env, Port port) { 3 // 初始化网络 4 if (!initializeWinsockIfNecessary()) { 5 socketErr(env, "Failed to initialize 'winsock': "); 6 return -1; 7 } 8 // 创建数据报套接字 9 int newSocket = createSocket(SOCK_DGRAM); 10 if (newSocket < 0) { 11 socketErr(env, "unable to create datagram socket: "); 12 return newSocket; 13 } 14 // 获取env的groupsockPriv重新使用标识 15 int reuseFlag = groupsockPriv(env)->reuseFlag; 16 // 根据需要,为env释放groupsockPriv成员指向对象 17 reclaimGroupsockPriv(env); 18 19 // 设置允许重用本地地址和端口,reuseFlag用来接受传出值 20 if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR, 21 (const char*)&reuseFlag, sizeof reuseFlag) < 0) { 22 socketErr(env, "setsockopt(SO_REUSEADDR) error: "); 23 closeSocket(newSocket); 24 return -1; 25 } 26 27 #if defined(__WIN32__) || defined(_WIN32) 28 // Windoze doesn't properly handle SO_REUSEPORT or IP_MULTICAST_LOOP 29 // win-doze 贬义,可能是由于操作系统BUG很多,而且运行速度慢,导致在运行的是后你会DOZE(打瞌睡) 30 // Windows无法正确的处理SO_REUSEPORT或 IP_MULTICAST_LOOP 31 #else 32 #ifdef SO_REUSEPORT //在定义了重新使用端口宏下设置 33 if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT, 34 (const char*)&reuseFlag, sizeof reuseFlag) < 0) { 35 socketErr(env, "setsockopt(SO_REUSEPORT) error: "); 36 closeSocket(newSocket); 37 return -1; 38 } 39 #endif 40 41 #ifdef IP_MULTICAST_LOOP //在定义了IP多播循环下设置 42 const u_int8_t loop = 1; 43 if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP, 44 (const char*)&loop, sizeof loop) < 0) { 45 socketErr(env, "setsockopt(IP_MULTICAST_LOOP) error: "); 46 closeSocket(newSocket); 47 return -1; 48 } 49 #endif 50 #endif 51 // Note: Windoze requires binding, even if the port number is 0 52 // Windows 需要绑定,即使端口号是0 53 netAddressBits addr = INADDR_ANY; // 设置绑定地址是任意网口IP 54 #if defined(__WIN32__) || defined(_WIN32) 55 #else 56 if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) { 57 //ReceivingInterfaceAddr是一个全局的定义,默认是INADDR_ANY 58 #endif 59 if (port.num() == 0) addr = ReceivingInterfaceAddr; 60 // 组建sockaddr_in结构体 61 MAKE_SOCKADDR_IN(name, addr, port.num()); 62 // 绑定socket套接口和sockaddr地址 63 if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) { 64 char tmpBuffer[100]; 65 sprintf(tmpBuffer, "bind() error (port number: %d): ", 66 ntohs(port.num())); 67 socketErr(env, tmpBuffer); 68 closeSocket(newSocket); 69 return -1; 70 } 71 #if defined(__WIN32__) || defined(_WIN32) 72 #else 73 } 74 #endif 75 76 // Set the sending interface for multicasts, if it's not the default: 77 // 设置多播发送接口,如果它不是默认的: 78 if (SendingInterfaceAddr != INADDR_ANY) { 79 struct in_addr addr; 80 addr.s_addr = SendingInterfaceAddr; 81 // 设置多播接口 82 if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF, 83 (const char*)&addr, sizeof addr) < 0) { 84 socketErr(env, "error setting outgoing multicast interface: "); 85 closeSocket(newSocket); 86 return -1; 87 } 88 } 89 90 return newSocket; 91 }