dword readtotaltimeoutmultiplier;
dword readtotaltimeoutconstant;
dword writetotaltimeoutmultiplier;
dword writetotaltimeoutconstant;
} commtimeouts,*lpcommtimeouts;
区间超时:(仅对从端口中读取数据有用)它指定在读取两个字符之间要经历的时间
总超时: 当读或写特定的字节数需要的总时间超过某一阈值时,超时触发.
超时公式:
readtotaltimeout = (readtotaltimeoutmultiplier * bytes_to_read)
+ readtotaltimeoutconstant
writetotaltimeout = (writetotaltimeoutmuliplier * bytes_to_write)
+ writetototaltimeoutconstant
note:在设置超时时参数0为无限等待,既无超时
参数maxdword为立即返回
超时设置:
getcommtimeouts(hcomm,&timeouts);
setcommtimeouts(hcomm,&timeouts);
10.查询方式读写数据
例程:
commtimeouts to;
dword readthread(lpdword lpdwparam)
{
byte inbuff[100];
dword nbytesread;
if(!(cp.dwprovcapabilities&pcf_inttimeouts))
return 1l;
memset(&to,0,sizeof(to));
to.readintervaltimeout = maxdword;
setcommtimeouts(hcomm,&to);
while(breading)
{
if(!readfile(hcomm,inbuff,100,&nbytesread,null))
locprocesscommerror(getlasterror());
else
if(nbytesread)
locprocessbytes(inbuff,nbytesread);
}
purgecomm(hcomm,purge_rxclear);
return 0l;
}
note:
purgecomm()是一个清除函数,它可以中止任何未决的后台读或写,并且可以冲掉i/o缓冲区.
bool purgecomm(handle hfile,dword dwflags);
dwflages的有效值:
purge_txabort: 中止后台写操作
pruge_rxabort: 中止后台读操作
pruge_txclear: 清除发送缓冲区
pruge_rxclear: 清除接收缓冲区
技巧:
可通过clearcommerror()来确定接收缓区中处于等待的字节数。
bool clearcommerror(
handle hfile, // handle to communications device
lpdword lperrors, // pointer to variable to receive error codes
lpcomstat lpstat // pointer to buffer for communications status
);
clearcommerror()将返回一个comstat结构:
typedef struct _comstat { // cst
dword fctshold : 1; // tx waiting for cts signal
dword fdsrhold : 1; // tx waiting for dsr signal
dword frlsdhold : 1; // tx waiting for rlsd signal
dword fxoffhold : 1; // tx waiting, xoff char rec`d
dword fxoffsent : 1; // tx waiting, xoff char sent
dword feof : 1; // eof character sent
dword ftxim : 1; // character waiting for tx
dword freserved : 25; // reserved
dword cbinque; // bytes in input buffer
dword cboutque; // bytes in output buffer
} comstat, *lpcomstat;
其中的cbinque和cboutque中即为缓冲区字节。
11.同步i/o读写数据
commtiomouts to;
dword readthread(lpdword lpdwparam)
{
byte inbuff[100];
dword nbyteread,dwerrormask,ntoread;
comstat comstat;
if(!cp.dwprovcapabilities&pcf_totaltimeouts)
return 1l;
memset(&to,0,sizeof(to));
to.readtotaltimeoutmultiplier = 5;
to.readtotaltimeoutconstant = 50;
setcommtimeouts(hcomm,&to);
while(breading)
{
clearcommerror(hcomm,&dwerrormask,&comstat);
if(dwerrormask)
locprocesscommerror(dwerrormask);
if(comstat.cbinque >100)
ntoread = 100;
else
ntoread = comstat.cbinque;
if(ntoread == 0)
continue;
if(!readfile(hcomm,inbuff,ntoread,&nbytesread,null))
locprocesscommerror(getlasterror());
else
if(nbytesread)
locprocessbytes(inbuff,nbytesread);
}
return 0l;
}
12.异步i/o读写数据
当createfile()中的fdwattrsandflags参数为file_flag_overlappen时, 端口是为异步i/o打开的,此时可以在readfile的最后一个参数中指定一个overlapped结构,使数据的读操作在后台进行。windows 95包括了异步i/o的许多变种。
typedef struct _overlapped {
dword internal;
dword internalhigh;
dword offset;
dword offsethigh;
handle hevent;
} overlapped;
对于串行口仅hevent成员有效,其于成员必须为0。
例程:
commtimeouts to;
...
dword readthread((lpdword lpdwparam)
{
byte inbuff[100];
dword nrytesread,endtime,lrc;
static overlapped o;
if(!cp.dwprovcapabilities & pcf_totaltimeouts)
return 1l;
memset(&to,0,sizeof(to));
to.readtotaltimeoutmultiplier = 5;
to.readtotaltimeoutconstant = 1000;
setcommtimeouts(hcomm,&to);
o.hevent = createevent(null,true,false,null);
while(breading)
{
if(!readfile(hcomm,inbuff,10,&nbytesread,&o))
{
nbytesread = 0;
if(lrc=getlasterror() == error_io_pending)
{
endtime = gettickcount() + 1000;
while(!getoverlappedresult(hcomm,&o,&nbytesread,false))
if(gettickcount() > endtime) break;
}
if(nbytesread) locprocessbytes(inbuff,nbytesread);
}
else
{
if(nbytesread) locprocessbytes(inbuff,nbytesread);
resetevent(o.hevent);
}
}
purgecomm(hcomm,purge_rxclear);
return 0l;
}
这一例程是对一开始读缓冲区就读到所需的字节时的处理:
while(breading)
{
if(!readfile(hcomm,inbuff,10,&nbytesread,&o))
{