2.4.3 创建监听套接字
PostgreSQL允许通过网络(TCP、Bonjour等)或UNIX本地机来访问数据库,本节主要介绍一下如何创建TCP套接字。在介绍创建套接字之前,先介绍以下主要数据结构。
字符串ListenAddresses:该字符串中存储的是服务器的IP地址,如果是多接口主机的话,IP地址之间用“,”隔开,“*”表示所有可用IP接口,缺省值为“localhost”。
整型数组ListenSocket[MAXLISTEN]:该数组用来保存与服务器上某个IP地址(一个服务器可能有多个网卡,因此会设置多个IP地址)绑定的监听套接字描述符,初始时全为-1。MAXLISTEN的值为64。
struct addrinfo结构体:该结构体用来保存我们调用getaddrinfo系统函数返回与协议无关的套接字时需要关心的信息,如要监听的服务器IP地址、服务器端口等相关信息。其结构如数据结构2.4所示。
数据结构2.4 addrinfo
struct addrinfo
{
int ai_flags; //AI_PASSIVE,AI_CANONNAME
intai_family;//地址族协议
intai_socktype;//套接口类型
intai_protocol;//0或者IPv4、IPv6选项
size_tai_addrlen;//套接口地址结构长度
struct sockaddr*ai_addr;//套接口地址指针
char*ai_canonname;//主机规范名
struct addrinfo*ai_next;//指向下一个struct addrinfo的指针
};
Postmaster首先调用SplitIdentifierString函数解析字符串ListenAddresses,得到多个服务器IP地址并构成一个List(参见数据结构2.5)。然后取出每一个服务器地址,调用函数StreamServerPort在该地址上创建一个监听套接口,并将返回的套接字描述符保存在整型数组ListenSocket[MAXLISTEN]的第一个值为-1的单元中。
数据结构2.5 Listtypedef
struct List
{
NodeTag type; //T_List,T_IntList,or T_OidList
intlength;//链表长度
ListCell*head;//链表的头节点
ListCell*tail;//链表的尾节点
}List;
List是PostgreSQL中常用的一种链表结构,它的节点类型为ListCell(参见数据结构2.6),在ListCell中可以包含指向任何数据结构的指针。正是因为List和ListCell的独特设计,使得List能够用于建立任何数据类型的链表,在后面的内容中我们还将见到很多使用List的情况。
数据结构2.6 ListCell
struct ListCell
{
union
{
vOid *ptr_value;//T_List时指向该节点所对应的数据结构
int int_value;//T_IntList时记录整数值
Oid Oid_value;//T_OidList时记录OID值
}data;
ListCell *next;//指向链表中的下一个节点
};
StreamServerPort函数在创建监听套接字的时候,首先会填写addrinfo结构体。这里由于创建的是服务器套接字,所以将ai_flags设置为AI_PASSIVE表示该套接字为被动打开,ai_socktype置为SOCK_STREAM表示将要创建的是个字节流的套接口,ai_family将会根据具体情况设置,可以为AF_INET、AF_INET6和AF_UNIX,分别表示IPv4、IPv6和UNIX套接字。完成这些设置之后就可以调用系统函数getaddrinfo来根据服务器地址、服务器端口号对初始addrinfo结构体进行补充,填写其中的套接口地址等关键信息,从而得到一个完整的套接口,最后依次调用socket、bind、listen系统函数就可以创建一个监听套接字了。
socket函数先创建一个socket对象,bind函数则将由getaddrinfo函数补充完整的addrinfo结构体变量和socket对象进行绑定,最后通过listen函数对绑定的套接口进行监听,返回一个监听套接字。处于监听状态的流套接字将维护一个客户端连接请求队列,listen函数的第二个参数设定了该队列最多容纳的客户端连接请求数。如果当一个连接请求到来时,队列已满,那么客户端将收到一个WSAECONNREFUSED错误。
接下来,将调用reset_shared函数创建用于进程间通信的共享内存和信号量,在这之后装载用户认证文件pg_hba.conf和pg_ident.conf,初始化BackendList后台进程双向链表,并创建postmaster.opts文件。
BackendList是一个活动的后台进程表,主要用于跟踪和了解目前有多少子进程,并且在必要的时候给它们发送适当的信号。该进程表主要记录的是由Postmaster通过fork产生的Postgres进程,特殊的子进程例如Startup和BgWriter不在这个表中。
创建监听套接字的代码可参见Postmaster.c文件中的第800~900行。
【责任编辑:云霞 TEL:(010)68476606】