网络IO模型目的是一样的,只不过不同操作系统不同技术导致了不少差异。我们知道基于berkerly socket来说,IO模型只会有3个动作比较重要,1、创建传输通道;2、发送数据;3、接收数据。对我们来说,也只是需要这些信息。在接口定义中,我们设计vtp/intf/link,这3种对象。vtp代表了一个总的管理系统,包含多个Intf,intf对应了一个真实的socket,包含多个link,而link就是传输通道。但是同样是link,epoll跟iocp会有所不同,因此,我们需要为不同的IO模型提供一个渠道,让他们自定制需要的link,同时还为我们提供需要的link信息。驱动是个不错的选择。
驱动是多个API回调函数的界面,回调函数的实现,依赖于不同IO模型。
struct _vtp_driver_st{
vtpiom_t *(*vtpiom_new)() ;
void (*vtpiom_free)(vtpiom_t *vtpiom) ;
intf_t *(*intf_new)(vtpiom_t *iom) ;
void (*intf_free)(vtpiom_t *iom , intf_t *intf) ;
link_t *(*link_new)(vtpiom_t *iom , intf_t *intf) ;
void (*link_free)(vtpiom_t *iom , intf_t *intf , link_t *link) ;
int (*add_intf)(vtpiom_t *iom , intf_t *intf) ;
int (*del_intf)(vtpiom_t *iom , intf_t *intf) ;
int (*intf_income)(vtpiom_t *iom , intf_t *intf) ;
int (*add_link)(vtpiom_t *iom , link_t *link) ;
int (*del_link)(vtpiom_t *iom , link_t *link) ;
int (*link_recv)(vtpiom_t *iom , link_t *link) ;
int (*link_send)(vtpiom_t *iom , link_t *link) ;
int (*vtpiom_wait)(vtpiom_t *iom , vtpiom_event_t *events , int count , int timeout) ;
} ;
vtpiom_t是驱动的一个实例,由于驱动本身只是个API接口,因此,操作对象是不可缺少。vtpiom同时也对应了iocp的CreateIoCompletionPort,或者epoll中的epoll_create。我们在【1】中讨论了,iocp和epoll在io时区别,当一个link被创建时,他自动发送一个信号给GetQueuedCompletionStatus,这个行为就和epoll_wait一样了。如果我们允许iocp的recv接收到空缓冲区,实际上就可以将所有的io模型给统一起来了。vtp_driver_t定义的接口,就可以涵盖所有的io模型。
我们为vtp_t指定一种驱动,并绑定一个vtpiom_t,那么所有定义在【2】中的操作都完整统一起来了。