第5章基于插口的高级网络编程接口NPORT.docx
- 文档编号:12096926
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:52
- 大小:34.30KB
第5章基于插口的高级网络编程接口NPORT.docx
《第5章基于插口的高级网络编程接口NPORT.docx》由会员分享,可在线阅读,更多相关《第5章基于插口的高级网络编程接口NPORT.docx(52页珍藏版)》请在冰豆网上搜索。
第5章基于插口的高级网络编程接口NPORT
第5章基于插口的高级网络编程接口NPORT
本章介绍一个高级插口应用编程接口NPORT。
NPORT为用户提供一个简化的、方便的高级网络编程接口。
5-1概述
为了简化TCP和UDP插口编程,我们设计了一个基于插口的高级网络编程插口,NPORT。
NPORT的基本思想是将一个TCP连接的两端或UDP通信的双方用一个数据结构来描述,这个数据结构就是NPORT。
以此为基础,封装基本的插口函数,简化用户编程。
NPORT中记录了与通信双方有关的基本信息,这些信息包括:
本地IP地址,本地端口,对等IP地址,对等端口,插口描述符,插口地址域,插口类型,通信模式,插口状态,读写状态。
大部分NPORT函数都有一个NPORT类型的传入参数,该参数相当于插口API中的插口描述符参数。
5-2基本数据结构NPORT
NPORT高级编程接口的头文件nport.h中定义了接口所需的基本数据结构、宏定义和函数原型。
头文件的内容如程序5-1所示。
程序5-1NPORT编程接口头文件nport.h。
1#ifndef_NPORT2#define_NPORT34#include
7#include
8#include
9#include
10#include
11#include
12#include
13#include
14#include
15#include
16
17#defineNPORT_MODE_NOBLOCK1
18#defineNPORT_MODE_BLOCK0
19#defineNPORT_NAMELEN32
20
21#defineNPORT_STATE_INIT0
22#defineNPORT_STATE_OPEN1
23#defineNPORT_STATE_CONN2
24#defineNPORT_STATE_CLOSE0
25#defineNPORT_STATE_RCLOSE3
26#defineNPORT_STATE_WCLOSE4
27
28#defineNPORT_ERROR-1
29#defineNPORT_DISCONNECTED-2
30#defineNPORT_NO_DATA_BUF-3
31#defineNPORT_CALLERROR-4
32#defineNPORT_SUCCEED0
33
34typedefstruct{
35unsignedshortlport;/*本地端口*/
36charlname[NPORT_NAMELEN];/*本地IP地址*/
37intsocket;/*本地插口*/
38unsignedshortrport;/*对等端口*/
39charrname[NPORT_NAMELEN];/*对等IP地址*/
40intdomain;/*插口地址域*/
41inttype;/*协议类型*/
42intmode;/*通信模式*/
43charopened;/*插口状态*/
44charrflag,wflag,oflag;/*可读标志,可写标志,OOB数据标志*/
45}NPORT;
46intNPORTInit(NPORT*this);47intNPORTModeBlock(NPORT*this);48intNPORTModeNoBlock(NPORT*this);49intNPORTSOpen(NPORT*this);50intNPORTCOpen(NPORT*this);51intNPORTDBOpen(NPORT*this);
52intNPORTDOpen(NPORT*this);
53intNPORTSPNumber(NPORT*this,intnum);
54intNPORTSAccept(NPORT*this,NPORT*conn);
55intNPORTCRequest(NPORT*cli);
56intNPORTLocalName(NPORT*this,char*name);
57intNPORTLocalPort(NPORT*this,unsignedshortport);
58intNPORTRemoteName(NPORT*this,char*name);
59intNPORTRemotePort(NPORT*this,unsignedshortport);
60intNPORTWrtRdy(NPORT*this,intnum,intsec,intusec);
61intNPORTMsgRdy(NPORT*this,intnum,intsec,intusec);
62intNPORTOOBRdy(NPORT*this,intnum,intsec,intusec);
63intNPORTLRead(NPORT*this,charbuf[],intlen,intflag);
64intNPORTLWrite(NPORT*this,charbuf[],intlen,intflag);
65intNPORTDPRead(NPORT*this,charbuf[],intlen);
66intNPORTDPWrite(NPORT*this,charbuf[],intlen);
67intNPORTDBWrite(NPORT*this,charbuf[],intlen);
68intNPORTClose(NPORT*this);
69intNPORTShutdown(NPORT*this,intmode);70intNPORTRWError();71#endif
第17~18行定义NPORT的通信模式:
阻塞模式(NPORT_MODE_BLOCK)和非阻塞模式(NPORT_MODE_NOBLOCK)。
第21~26行定义NPORT的状态。
NPORT一共有六种状态,如表5-1所示。
其中状态NPORT_STATE_INIT和NPORT_STATE_CLOSE的状态值是一样的。
表5-1NPORT端口的六种状态
状态名
说明
NPORT_STATE_INIT
NPORT端口已被初始化
NPORT_STATE_OPEN
NPORT端口已被成功打开
NPORT_STATE_CONN
NPORT端口已建立连接
NPORT_STATE_CLOSE
NPORT端口的读写通道均被关闭
NPORT_STATE_RCLOSE
NPORT端口的读通道被关闭
NPORT_STATE_WCLOSE
NPORT端口的写通道被关闭
第28~32行定义NPORT函数的返回值。
一共有五种预定义的返回值,如表5-2所示。
在NPORT接口中,将NPORT函数调用失败分为四种类型:
一般性错误,严重错误(链路断),读写条件不满足,NPORT传入参数值不对。
除返回值为NPORT_SUCCEED和NPORT_CALLERROR外,对于其他的返回值,应用程序均可通过errno了解更进一步的情况,因为这些错误是由于调用插口函数而引起的。
第34~45行定义结构NPORT。
对于TCP而言,rname和rport为连接的对方的IP地址和端口号。
对于UDP而言,rname和rport为接收到的数据报的源IP地址和端口号或发送数据报的目的地的IP地址和端口号。
目前,NPORT只支持协议族AF_INET,即只支持TCP/IP协议中的TCP和UDP编程,domain成员值等于AF_INET。
而type成员值为SOCK_STREAM和SOCK_DGRAM。
写标志(wflag)由函数NPORTWrtRdy()修改,读标志(rflag)由函数NPORTMsgRdy()修改,OOB数据标志(oflag)由函数NPORTOOBRdy()修改。
如果标志位为1表示条件满足,为0则表示条件不满足。
NPORT端口结构中没有发送和接收缓存,而是直接利用插口API中的发送和接收缓存。
第46~68行NPORT接口函数原型说明。
表5-2NPORT函数返回值定义
返回值
含义
NPORT_ERROR
函数调用出现一般性错误
NPORT_DISCONNECTED
TCP连接已断
NPORT_CALLERROR
NPORT端口的状态不对或传入参数不对
NPORT_NO_DATA_BUF
没有数据可读或没有可用插口缓存
NPORT_SUCCEED
调用成功
所有使用NPORT接口函数的程序中均需要包括此头文件。
5-3NPORT中的功能函数
NPORT接口共有25个函数,如表5-3所示。
表5-3NPORT接口函数
类型
函数名
功能描述
参数设置
intNPORTInit(NPORT*this)
初始化NPORT端口this
intNPORTModeBlock(NPORT*this);
将this置为阻塞模式
intNPORTModeNoBlock(NPORT*this);
将this置为非阻塞模式
intNPORTSPNumber(NPORT*this,intnum);
将this置为服务器方式
intNPORTLocalName(NPORT*this,char*name);
设置this的本地IP地址
intNPORTLocalPort(NPORT*this,unsignedshortport);
设置this的本地端口号
intNPORTRemoteName(NPORT*this,char*name);
设置this的对端端口号
intNPORTRemotePort(NPORT*this,unsignedshortport);
设置this的对端IP地址
端口管理
intNPORTSOpen(NPORT*this);
打开一个TCP服务器NPORT端口
intNPORTCOpen(NPORT*this);
打开一个TCP客户端NPORT端口
intNPORTDBOpen(NPORT*this);
打开一个NPORT广播端口
intNPORTDOpen(NPORT*this);
打开一个NPORT数据报端口
intNPORTClose(NPORT*this);
关闭一个NPORT端口
intNPORTShutdown(NPORT*this,intmode);
按指定模式mode关闭NPORT端口
连接建立
intNPORTSAccept(NPORT*this,NPORT*conn);
等待TCP客户端的建连请求
intNPORTCRequest(NPORT*cli);
请求同TCP服务器建立连接
(续表5-3)
读写状态
intNPORTWrtRdy(NPORT*this,intnum,intsec,intusec);
NPORT端口this可写
intNPORTMsgRdy(NPORT*this,intnum,intsec,intusec);
NPORT端口this可读
intNPORTOOBRdy(NPORT*this,intnum,intsec,intusec);
NPORT端口this上有带外数据可读
读写函数
intNPORTLRead(NPORT*this,charbuf[],intlen,intflag);
读TCPNPORT端口
intNPORTLWrite(NPORT*this,charbuf[],intlen,intflag);
写TCPNPORT端口
intNPORTDPRead(NPORT*this,charbuf[],intlen);
读UDPNPORT端口
intNPORTDPWrite(NPORT*this,charbuf[],intlen);
写UDPNPORT端口
intNPORTDBWrite(NPORT*this,charbuf[],intlen);
发送广播
错误处理
intNPORTRWError();
处理NPORT端口上的读写错误
下面我们来详细介绍表5-3中的函数。
5-3-1NPORTInit函数
NPORTInit()函数代码如程序5-2所示,它的主要功能是初始化一个NPORT端口。
在使用一个NPORT之前,必须调用NPORTInit函数来初始化它。
该函数只有一个传入参数this,即要初始化的NPORT端口指针。
它将NPORT端口的本地IP地址和对端IP地址都初始化为空串,本地端口号和对端端口号都初始化0。
如果应用程序不改变它们的初始化值,则相当于告知内核为插口自动分配IP地址和端口号。
NPORTInit将NPORT的地址域初始化为AF_INET,插口类型置为SOCK_STREAM,即默认情况下,NPORT端口为TCP/IP协议中的TCP插口。
同时将通信模式初始化为阻塞模式(NPORT_MODE_BLOCK)。
初始化完成时NPORT的状态处于初始化状态(NPORT_STATE_INIT)。
程序5-2函数NPORTInit源代码。
1intNPORTInit(NPORT*this)2{3this->lport=this->rport=0;4this->lname[0]=this->rname[0]=0;5this->socket=0;6this->domain=AF_INET;7this->type=SOCK_STREAM;8this->mode=NPORT_MODE_BLOCK;
9this->opened=NPORT_STATE_INIT;
10this->rflag=this->wflag=this->oflag=0;
11}
5-3-2NPORTModeBlock和NPORTModeNoBlock函数
函数NPORTModeBlock的源代码如程序5-3所示,它的主要功能是将NPORT端口this置为阻塞模式。
函数NPORTModeNoBlock的源代码如程序5-4所示,它的主要功能是将NPORT端口this置为非阻塞模式。
如果调用成功,它们都返回NPORT_SUCCEED,如果this指向的NPORT没有打开,将返回NPORT_CALLERROR,如果ioctl调用失败将返回NPORT_ERROR。
程序5-3函数NPORTModeBlock源代码。
1intNPORTModeBlock(NPORT*this)2{3if(!
this->opened)returnNPORT_CALLERROR;4if(this->mode==NPORT_MODE_BLOCK)returnNPORT_SUCCEED;
5this->mode=NPORT_MODE_BLOCK;
6if(ioctl(this->socket,FIONBIO,&this->mode)<0)returnNPORT_ERROR;
7elsereturnNPORT_SUCCEED;
8}
程序5-4函数NPORTModeNoBlock源代码。
1intNPORTModeNoBlock(NPORT*this)2{
3if(!
this->opened)returnNPORT_ERROR;
4if(this->mode==NPORT_MODE_NOBLOCK)returnNPORT_SUCCEED;
5this->mode=NPORT_MODE_NOBLOCK;
6if(ioctl(this->socket,FIONBIO,&this->mode)<0)returnNPORT_ERROR;
7elsereturnNPORT_SUCCEED;
8}
5-3-3函数NPORTLocalPort和NPORTLocalName
函数NPORTLocalPort将this指向的NPORT端口中的本地端口号置为port,NPORTLocalName函数的功能则是将this指向的NPORT端口中的本地IP地址(lname)置为name指向的字符串。
本地IP地址的格式为点分十进制字符串。
可以将函数NPORTLocalName进一步扩充,name既可指向网络接口名,也可以指向网络接口的点分十进制IP地址。
这个工作留给读者去完成(习题5-1)。
这两个函数的源代码分别如程序5-5和程序5-6所示。
程序5-5函数NPORTLocalPort源代码。
1intNPORTLocalPort(NPORT*this,unsignedshortport)2{3this->lport=port;4returnNPORT_SUCCEED;5}
程序5-6函数NPORTLocalName源代码。
1intNPORTLocalName(NPORT*this,char*name)
2{
3strcpy(this->lname,name);
4returnNPORT_SUCCEED;
5}
5-3-4函数NPORTRemotePort和NPORTRemoteName
函数NPORTRemotePort将this指向的NPORT端口中的对端端口号置为port,NPORTRemoteName函数的功能则是将this指向的NPORT端口中的对端IP地址(rname)置为name指向的字符串。
对端IP地址的格式为点分十进制字符串。
同样可以将函数NPORTRemoteName进一步扩充,name既可指向网络接口名,也可以指向网络接口的点分十进制IP地址。
这个工作留给读者去完成(习题5-2)。
这两个函数的源代码分别如程序5-7和程序5-8所示。
程序5-7函数NPORTRemotePort源代码。
1intNPORTRemotePort(NPORT*this,unsignedshortport)2{3this->rport=port;4returnNPORT_SUCCEED;
5}
程序5-8函数NPORTRemoteName源代码。
1intNPORTRemoteName(NPORT*this,char*name)2{3strcpy(this->rname,name);4returnNPORT_SUCCEED;5}
前面介绍的这些函数基本上都是设置NPORT端口的某一个成员值,提供这些函数的目的是向应用编程人员屏蔽NPORT结构的细节。
5-3-5函数NPORTSPNumber
函数NPORTSPNumber的主要功能是将this指向的NPORT端口置为服务器口,参数num指定服务器端口能同时接收的TCP连接请求数。
这个函数只是简单地调用插口函数listen来完成,函数源代码如程序5-9所示。
应用可以不调用此函数,因为打开一个服务器口函数NPORTSOpen()中已调用listen函数,并将num置为8,所以如果应用程序不需要改变这个值,就不需要调用NPORTSPNumber()函数。
程序5-9函数NPORTSPNumber源代码。
1intNPORTSPNumber(NPORT*this,intnum)
2{
3if(!
this->opened)returnNPORT_CALLERROR;
4if(listen(this->socket,num)<0)
5{
6#ifdefDEBUG
7printf("调用listen失败,errno=%d\n",errno);
8#endif
9returnNPORT_ERROR;
10}
11returnNPORT_SUCCEED;
12}
5-3-6函数NPORTClose和NPORTShutdown
函数NPORTClose的主要功能关闭this指向的NPORT端口,函数的源代码如程序5-10所示。
该函数首先判断NPORT端口是否已关闭,如果已处于关闭状态则直接返回NPORT_SUCCEED,否则调用close函数关闭NPORT端口中的插口(socket)。
如果调用失败则返回NPORT_ERROR,否则将NPORT端口的状态置为NPORT_STATE_CLOSE,清除socket,并返回NPORT_SUCCEED。
如果定义了调试代码宏(DEBUG),则函数还打印调试报文(后面的函数也有类似的功能,就不再说明)。
需要说明的是,在多线程环境中,printf函数可能不是多线程安全的,有关多线程程序设计将在下一章介绍。
程序5-10函数NPORTClose源代码。
1intNPORTClose(NPORT*this)2{3if(this->opened==NPORT_STATE_CLOSE)returnNPORT_SUCCEED;
4if(close(this->socket)==-1)returnNPORT_ERROR;
5if(this->opened==NPORT_STATE_CONN)
6{
7#ifdefDEBUG
8printf("成功地关闭同主机[%s]上的端口[%d]的连接\n",this->rname,this->rport);
9#endif
10}
11else
12if(this->opened==NPORT_STATE_OPEN)
13{
14#ifdefDEBUG
15printf("成功地关闭插口[%d]\n",this->lport);
16#endif
17}
18this->socket=0;
19this->opened=NPORT_STATE_CLOSE;
20returnNPORT_SUCCEED;
21}
函数NPORTShutdown的功能是按指定方式(mode)关闭this指向的NPORT端口,它的功能类似于基本插口函数shutdown。
实际上,它是通过调用shutdown函数来完成NPORT端口中的插口的关闭动作。
函数的源代码如程序5-11所示。
参数mode的含义与shutdown函数的第二个参数mode的含义是一样的。
程序5-11函数NPORTShutdown源代码。
1intNPORTShutdown(NPORT*this,i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 插口 高级 网络 编程 接口 NPORT