您的位置:首页 > 理论基础 > 计算机网络

3.6 网络编程与reactor模式

2016-04-07 09:43 561 查看
postfix的网络编程内容可以分为三部分:

1inet_listen.c、unix_listen.c、fifo_listen.c实现服务器端,即实现基本的socket,listen,bind,accept,mkfifo等调用。

2inet_connect.c、unix_connect.c实现了客户端。

3inet_trigger.c、unix_trigger.c、fifo_trigger.c实现了“触发”式的客户端。

这里的“触发”指的是:不进行“会话”而仅仅是发送一次数据随即断开连接。

“触发”有两种方式:定时的和不定时的。qmgr和pickup模块需要被定时触发。定时触发在4.3.4中的master_wakeup_timer_event函数中实现(详情见4.3.4):

/master/master_wakeup.c
static char wakeup = TRIGGER_REQ_WAKEUP;
switch (serv->type) {
case MASTER_SERV_TYPE_INET:
status = inet_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
case MASTER_SERV_TYPE_UNIX:
status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
#ifdef MASTER_SERV_TYPE_PASS
case MASTER_SERV_TYPE_PASS:
status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;


不定时的触发如cleanup模块向邮件队列(文件系统)写数据后,要触发qmgr模块,在/global/mail_stream.c的mail_stream_finish_file函数中,用vstream_fflush写数据后,调用mail_trigger触发qmgr模块。这类触发不需要定时事件,一旦cleanup模块完成写数据都会发生。

在smtp协议解析过程中,客户端与服务器端要进行你来我往的“交流”,而在cleanup模块将信件整理为record格式通知qmgr模块进行调度的场景中,cleanup模块仅需要“通知”一下qmgr模块,而不需要进行“会话”。所以smtpd.c使用了single_server.c做模板而qmgr.c使用了trigger_server.c做模板(见4.4)。

我们来看一下inet_trigger.c的inet_trigger函数

/util/inet_trigger.c
91 /* inet_trigger - wakeup INET-domain server */
92
93 int     inet_trigger(const char *service, const char *buf, ssize_t len, int timeout)
94 {
95     const char *myname = "inet_trigger";
96     struct inet_trigger *ip;
97     int     fd;
98
99     if (msg_verbose > 1)
100         msg_info("%s: service %s", myname, service);
101
102     /*
103      * Connect...
104      */
105     if ((fd = inet_connect(service, BLOCKING, timeout)) < 0) {
106         if (msg_verbose)
107             msg_warn("%s: connect to %s: %m", myname, service);
108         return (-1);
109     }
110     close_on_exec(fd, CLOSE_ON_EXEC);
111     ip = (struct inet_trigger *) mymalloc(sizeof(*ip));
112     ip->fd = fd;
113     ip->service = mystrdup(service);
114
115     /*
116      * Write the request...
117      */
118     if (write_buf(fd, buf, len, timeout) < 0
119         || write_buf(fd, "", 1, timeout) < 0)
120         if (msg_verbose)
121             msg_warn("%s: write to %s: %m", myname, service);
122
123     /*
124      * Wakeup when the peer disconnects, or when we lose patience.
125      */
126     if (timeout > 0)
127         event_request_timer(inet_trigger_event, (void *) ip, timeout + 100);
128     event_enable_read(fd, inet_trigger_event, (void *) ip);
129     return (0);
130 }


105 连接服务器,调用inet_connect.c中的inet_connect函数。

118-121 带超时的写。

126-128 安排一个时间事件,在此时间事件inet_trigger_event中执行close。即不进行“会话”,在一个限定时间内关闭连接。

仅靠基本的网络编程手段不足以应对网络编程的复杂性,我们还需要“模式”的支持,postfix采用了常见的Reactor模式:即结合多路复用函数和回调函数,当多路复用函数选定文件描述符后,执行相应的回调函数,实现“事件”编程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: