.7.3.3 数据传输
收发数据是网络编程的主题。要在已建立连接的套接字上接收数据,可用这两个A P I函数:
s e n d和W S A S e n d。第二个函数是Winsock 2中专有的。同样地,在已建立了连接的套接字上接收数据也有两个函数: r e c v和W S A R e c v。后者也是Winsock 2函数。

必须牢牢记住这一点:所有关系到收发数据的缓冲都属于简单的c h a r类型。也就是说,这些函数没有“U n i c o d e”版本。

另外,所有收发函数返回的错误代码都是S O C K E T _ E R R O R。一旦返回错误,系统就会调用W S A G e t L a s t E r r o r获得详细的错误信息。最常见的错误是W S A E C O N N A B O RT E D和W S A E C O N N R E S E T。两者均涉及到即将关闭连接这一问题—要么通过超时,要么通过通信方关闭连接。另一个常见错误是W S A E W O U L D B L O C K,一般出现在套接字处于非暂停模
式或异步状态时。这个错误主要意味着指定函数暂不能完成。

1. send和W S A S e n d
要在已建立连接的套接字上发送数据,第一个可用的A P I函数是s e n d,其原型为:

int send(
     SOCKET s,
     const char FAR * buf,
     int len,
     int flags
    );
S O C K E T参数是已建立连接的套接字,将在这个套接字上发送数据。第二个参数b u f,则是字符缓冲区,区内包含即将发送的数据。第三个参数l e n,指定即将发送的缓冲区内的字符数。最后,f l a g s可为0、M S G _ D O N T R O U T E或M S G _ O O B。另外, f l a g s还可以是对那些标志进行按位“或运算”的一个结果。M S G _ D O N T R O U T E标志要求传送层不要将它发出的包路
由出去。由基层的传送决定是否实现这一请求(例如,若传送协议不支持该选项,这一请求就会被忽略)。M S G _ O O B标志预示数据应该被带外发送。
对返回数据而言,s e n d返回发送的字节数;若发生错误,就返回S O C K E T _ E R R O R。常见的错误是W S A E C O N N A B O RT E D,这一错误一般发生在虚拟回路由于超时或协议有错而中断的时候。发生这种情况时,应该关闭这个套接字,因为它不能再用了。远程主机上的应用通过执行强行关闭或意外中断操作重新设置虚拟虚路时,或远程主机重新启动时,发生的则是W S A E C O N N R E S E T错误。再次提醒大家注意,发生这一错误时,应该关闭这个套接字。最
后一个常见错误是W S A E T I M E O U T,它发生在连接由于网络故障或远程连接系统异常死机而引起的连接中断时。
send API函数的Winsock 2版本是W S A S e n d,它的定义如下:

int WSASend(
       SOCKET s,
       LPWSABUF lpBuffers,
       DWORD   dwBufferCount,
       LPWORD  lpNumberOfBytesSent,
       DWORD   dwFlags,
       LPWSAOVERLAPPED lpOverlapped,
       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE
      );
这个套接字是一个连接会话的有效句柄。第二个参数是指向一个或多个W S A B U F结构的指针。它既可是一个独立的结构,又可以是一组结构。第三个参数指明准备投递的W S A B U F结构数。记住,每个W S A B U F结构本身就是一个字符缓冲和缓冲长度。为何打算同时发送多个缓冲呢?也许大家不太明白其中的原因。这就是我们稍后要讲的“分散集中I / O模式”;但是,在一个已建立连接的套接字上利用多缓冲来发送数据时,顺序是从第一个到最后一个W S A B U F结构。l p N u m b e r O f B y t e s S e n t是指向D W O R D(是W S A S e n d调用返回的)的指针,其中包含字节总发送数。d w F l a g s参数相当于它在s e n d中的等同物。最后两个参数—l p O v e r l a p p e d和l p C o m p l e t i o n R O U T I N E—用于重叠I / O。重叠I / O是Wi n s o c k支持的异步I / O模式之一,

W S A S e n d函数把l p N u m b e r O f B y t e s S e n t设为写入的字节数。成功的话,该函数就返回0,
否则就返回S O C K _ E R R O R,常见错误和s e n d函数的情形一样。

2. WSASendDisconnect
该函数非常特殊,一般不用。其原型是:

int WSASendDisconnect( 
            SOCKET s,
            LPWSABUF lpOUTboundDisconnectData
           );

该函数起初将套接字置为关闭状态,发送无连接的数据。当然,它只能用于支持从容关机和无连接数据的传输协议。目前还没有传输提供者支持无连接的数据。W S A S e n d D i s c o n n e c t函数的行为和利用S D _ S E N D参数调用s h u t d o w n 函数差不多,但它另外还要发送包含在b o u n d D i s c o n n e c t D a t a参数中的数据。后来的数据禁止在这个套接字上发送。如果调用失败,
W S A S e n d D i s c o n n e c t i o n就会返回S O C K E T _ E R R O R。使用该函数可能会出现s e n d函数中出现的某些错误。

带外数据
对已建立连接的流套接字上的应用来说,如果需要发送的数据比流上的普通数据重要得多,便可将这些重要数据标记成“带外数据”(Out-of-band, OOB)。位于连接另一端的应用可通过一个独立的逻辑信道(从概念上讲,该逻辑信道与数据流无关)来接收和处理O O B数据。
在T C P中,O O B数据由一个紧急1位标记(叫作U R G)和T C P分段头中的一个1 6位的指针组成。这里的标记和指针把指定的下行流字节当作紧急数据。实现紧急数据的两种特殊方法目前只能在T C P.RFC 793中见到,该索引对T C P进行了描述,并引入了“紧急数据”这一概念,表明T C P头中的紧急指针是紧急数据字节之后那个字节的绝对偏移。但是在RFC 11 2 2中,却将紧急偏移描述成指向紧急字节本身。
Wi n s o c k规格中,与协议无关的O O B数据和T C P的O O B数据实施(紧急数据)均采用了O O B这一术语。要查看待发数据中是否包含紧急数据,必须通过S I O C AT M A R K选项调用i o c t l s o c k e t函数。第9章将介绍S I O C AT M A R K的用法。
Wi n s o c k提供了获得紧急数据的几个方法。一是紧急数据一旦在线插入,它就会出现在普通数据流中;二是可以关闭在线插入,这样,不连续调用接收函数就会只返回紧急数据。至于控制O O B数据行为的套接字选项S O _ O O B I N L I N E,我们也将在第9章详细讨论。

Te l n e t和R l o g i n使用紧急数据是有原因的。尽管如此,除非你计划编写自己的Te l n e t和R l o g i n,否则就应该远离紧急数据。因为它不容易定义,而且其他平台上的实施情况可能和Wi n 3 2有所不同。在迫不得已的情况下使用紧急数据,必须发信号通知通信方为紧急数据执行
一个独立的控制套接字,并为普通数据的传输保留主要的套接字连接。

Posted on 2006-09-07 22:31 艾凡赫 阅读(627) 评论(0)  编辑 收藏 引用 所属分类: 网络编程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理