37 网络相关函数(五)——live555源码阅读(四)网络

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)。根据envgroupsockPriv成员来确定重用标识。如果groupsockPriv为空则使用默认设置。

setupDatagramSocket创建一个数据报形式的socket套接口,如果端口port 0,且ReceivingInterfaceAddrINADDR_ANY的时候,不进行绑定(bind)。否则若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 }
原文地址:https://www.cnblogs.com/oloroso/p/4724375.html