winsock编程(五)

来源:互联网 发布:淘宝店铺需要多少钱 编辑:程序博客网 时间:2024/05/02 00:37
 十.send函数
windows sockets的send函数在一个已经建立的连接上发送数据。

int send(

SOCKET s,

const char FAR* buf,

int len,

int flags

);

参数:
s[in] 一个指向已经建立的连接的描述符。

buf[in] 包含将要传输的数据的缓冲区。

len[in] 数据缓冲区的长度。

flags[in] 一个指出了调用方式的指示器。

注意:
send函数用于在一个已建立的连接上。对于面向消息的socket,必须小心以免包的大小不会超过底层服务所能提供的大小,底层服务提供的最大值可以通过getsockopt并用SO_MAX_MSG_SIZE。如果数据太长而不能通过底层服务自动传送,错误将会发生,返回的错误码为WSAMSGSIZE,并且不会传输任何数据。

send成功完成后不会指出数据是否已经成功传送了。

如果传输系统没有可用的缓冲区来传送数据,send将会阻塞进程直到socket的数据传完并被标记为非阻塞状态。在非阻塞的面向流的socket中,传输的字节范围是1到支持的最大长度,最大长度依赖于客户端和服务器的机器设置。select、WSASelect或者WSAEventSelect函数能用来检测是否可以发送新的数据。

调用send发送0长度的数据是允许的,此时,send将会返回0作为一个合法值。对于面向消息的socket,一个0长度的数据报被发送。

flags参数用于影响函数的行为,能有一些附加的socket的规范。函数的语义由socket和flags决定。这个参数可以用以下的值构造:

值(value) 意义(Meaning)

MSG_DONTROUTE 指出数据可以不服从于路由,windows sockets可能忽略这个选项。

MSG_OOB 发送无边界的数据(流风格的socket如SOCK_STREAM)。

返回值:
若没有错误发生,send函数返回已经发送的字节总数,该数目在非阻塞的socket中可能比传入的len参数要小。否则,返回SOCKET_ERROR,可用WSAGetLastError获取最后的错误码。

错误码:
WSANOTINITIALISED 未初始化socket,请先调用WSAStartup函数。

WSAENETDOWN 底层网络系统错误。

WSAEACCES 请求的地址是网络地址,但没有用setsockopt启用SO_BROADCAST选项。

WSAEINTR 一个阻塞的windows socets被调用WSACancelingBlockingCall取消。

WSAEINPROGRESS 线程被阻塞或者正在回调。

WSAEFAULT buf缓冲区和用户地址不一致。

WSAENETRESET 连接由于keep-alive信号检测到错误而中断。

WSAENOBUFS 没有缓冲区可用。

WSAENOTCONN socket还没有连接。

WSAENOTSOCK 描述符不是一个socket。

WSAEOPNOTSUPP 确定为MSG_OOB标记,但socket不是面向流样式的,无边界的数据不支持。

WSAESHUTDOWN socket已经被shutdown关闭。

WSAEWOULDBLOCK socket标记为非阻塞,但操作阻塞了进程。

WSAEMSGSIZE socket是面向消息的,但消息比底层网络系统支持的长度要长。

WSAEHOSTUNREACH 远程主机当前不可连接。

WSAEINVAL socket没有调用bind绑定,或者传递的flags参数错误。

WSAECONNABORTED 虚拟线路由于超时或者其他原因而终止,程序应该关闭这个socket,因为它不再可用了。

WSAECONNRESET 虚拟电路被远程主机执行硬性或者取消性的关闭。

WSAETIMEDOUT 连接丢失,由于网络错误或者另一端的计算机已经关闭。

十一.recv函数
windows sockets的recv函数从一个已经建立的连接接受数据。

int recv(

SOCKET s,

char FAR* buf,

int len,

int flags

);

参数:
s[in] 一个指向已经连接的socket的描述符。

buf[out] 收取的数据的缓冲区。

len[in] buf的长度。

flags[in] 调用的方式标志符。

注意:
recv函数用来在一个面向连接或者非连接的socket上读取数据。当使用的是面向连接的协议,sokcet必须先调用connect来连接。当调用面向无连接的socket时,socket在调用recv前必须调用bind绑定。

socket的本地地址必须已知。对于服务器端程序,使用明确的bind函数,或者使用不明确的accept/WSAAccept函数。明确的绑定函数不提倡在客户端使用。对于客户端程序,可以使用不明确的绑定函数如connect、WSAConnect、sendto、WSASendTo或者WSAJoinLeaf。

对于面向连接或者非连接的socket,这个函数限制了接受消息的地址。这个函数仅仅从远程地址返回消息。从其他地址传来的消息默认丢弃。

对于面向连接的socket(如SOCK_STREAM),调用recv将返回尽可能多当前可用的信息。若socket配置了内网接受无边界数据,外网无边界数据不可读,那么只有无边界数据将会被收取了。程序可以用ioctlsocket或者WSAIoctl标记命令检测是否有更多的信息到达。

对于面向非连接的socket(如SOCK_DATAGRAM),数据由第一个出列的数据报解析,数据报来自connect函数指定的目的地址。

若数据报或者消息比buf提供的缓冲区要长,buf缓冲区将由前面一部分数据填充,并且recv函数产生WSAMSGSIZE错误码。对于不可靠协议(如UDP),多出的数据将会丢失;对于可靠连接,数据将会保留直到分配了足够的缓冲空间并调用recv函数读取。对于TCP/IP,程序不能从多播网络接受信息,除非程序作为网络中的一员。

如果网络没有可以接受的数据,recv阻塞线程等待数据到达,此时socket遵守用MSG_PARTIAL标记为WSARecv设计的阻塞规则,除非socket是非阻塞的。这种情况下,SOCK_ERROR将会返回,错误代码是WSAWOULDBLOCK。select、WSASelect和WSAAsyncSelect或者WSAEventSelect函数用来检测是否有新数据到达。

若socket是面向连接的,且远程端已经用shutdown优美的关闭了连接,并且所有数据都已经到达,那么recv将会立即返回也不会收到任何字节。若连接已经被重置,recv函数将会返回WSAECONNRESET错误码。

flag参数影响recv函数。该标志的选择有:

MSG_PEEK Peek数据到缓冲区,并不从消息队列中移除。

MSG_OOB 处理无边界数据。

返回值:
如果没有错误,recv函数返回收到的字节数目。若连接被优美的关闭,返回的值是0。否则,返回SOCK_ERROR,可以用WSAGetLastError来获取最后的错误码。

错误码:
WSANOTINITIALISED 未初始化socket,请先调用WSAStartup函数。

WSAENETDOWN 底层网络系统错误。

WSAEFAULT buf参数指向的用户区不可用。

WSAENOTCONN socket未连接。

WSAEINTR 阻塞被调用WSACacelingBlocking取消。

WSAEINPROGRESS 线程被阻塞,或者在回调。

WSAENETRESET 连接被中断,由于发送的keep-alive消息错误。

WSAENOTSOCK 描述符不是一个socket。

WSAEOPNOTSUPP 传入了MSG_OOB标志,但socket不是面向流的。

WSAESHUTDOWN socket已经被关闭。

WSAEWOULDBLOCK socket标记为非阻塞,但receive操作将要阻塞socket。

WSAEMSGSIZE 消息太长而无法在缓冲区保存。

WSAEINVAL socket未使用bind绑定。

WSAECONNABORTED 虚拟电路由于超时或者其他问题被中断。

WSAETIMEDOUT 网络错误导致连接中断。

WSAECONNRESET 连接由另一端关闭
原创粉丝点击