简述:
禁止在一个上进行数据的接收与发送。
#include 或#include
int PASCAL FAR shutdown( SOCKET s, int how);
s:用于标识一个的描述字。
how:标志,用于描述禁止哪些操作。
注释:
shutdown()函数用于任何类型的禁止接收、禁止发送或禁止收发。
如果how参数为0,则该上的后续接收操作将被禁止。这对于低层协议无影响。对于TCP协议,TCP窗口不改变并接收前来的数据(但不确认)直至窗口满。对于UDP协议,接收并排队前来的数据。任何情况下都不会产生ICMP错误包。
若how为1,则禁止后续发送操作。对于TCP,将发送FIN。
若how为2,则同时禁止收和发。
请注意shutdown()函数并不关闭,且套接口所占有的资源将被一直保持到close()调用。
评注:
无论SO_LINGER设置与否,shutdown()函数不会阻塞。
一个应用程序不应依赖于重用一个已被shutdown()禁止的套接口。特别地,一个WINDOWS套接口实现不必支持在这样的套接口上使用()调用。
返回值:
如果没有错误发生,shutdown()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应。
:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS实现检测到网络子系统失效。
WSAEINVAL:how。
WSAEINPROGRESS:一个阻塞的WINDOWS调用正在运行中。
WSAENOTCONN:未连接(仅适用于SOCK_STREAM类型套接口)。
WSAENOTSOCK:描述字不是一个。
从函数调用上来分析(msdn):一旦完成了套接字的连接,应当将套接字关闭,并且释放其套接字句柄所占用的所有资源。真正释放一个已经打开的套接字句柄的资源直接调用closesocket即可,但要明白closesocket的调用可能会带来负面影响,具体的影响和如何调用有关,最明显的影响是数据丢失,因此一般都要在closesocket之前调用shutdown来关闭套接字。 shutdown:为了保证通信双方都能够收到应用程序发出的所有数据,一个合格的应用程序的做法是通知接受双发都不在发送数据!这就是所谓的“正常关闭 ”套接字的方法,而这个方法就是由shutdown函数,传递给它的参数有SD_RECEIVE,SD_SEND,SD_BOTH三种,如果是 SD_RECEIVE就表示不允许再对此套接字调用接受函数。这对于协议层没有影响,另外对于tcp套接字来说,无论数据是在等候接受还是即将抵达,都要重置连接(注意对于udp协议来说,仍然接受并排列传入的数据,因此udp套接字而言shutdown毫无意义)。如果选择SE_SEND,则表示不允许再调用发送函数。对于tcp套接字来说,这意味着会在所有数据发送出并得到接受端确认后产生一个FIN包。如果指定SD_BOTH,答案不言而喻。 closesocket:对此函数的调用会释放套接字的描述,这个道理众所周知(凡是经常翻阅msdn的),因此,调用此函数后,再是用此套接字就会发生调用失败,通常返回的错误是WSAENOTSOCK。此时与被closesocket的套接字描述符相关联的资源都会被释放,包括丢弃传输队列中的数据!!!!对于当前进程中的线程来讲,所有被关起的操作,或者是被挂起的重叠操作以及与其关联的任何事件,完成例程或的执行都将调用失败!另外 SO_LINGER标志还影响着closesocket的行为,但对于传统的socket程序,这里不加解释 因此可以可以看出shutdown对切断连接有着合理的完整性。 下面从tcp协议上来分析shutdown和closesocket的行为(behavior):closesocket或shutdown(使用 SD_SEND当作参数时),会向通信对方发出一个fin包,而此时套接字的状态会由ESTABLISHED变成FIN_WAIT_1,然后对方发送一个 ACK包作为回应,套接字又变成FIN_WAIT_2,如果对方也关闭了连接则对方会发出FIN,我方会回应一个ACK并将套接字置为 TIME_WAIT。因此可以看出closesocket,shutdown所进行的TCP行为是一样的,所不同的是函数部分,shutdown会确保 windows建立的数据传输队列中的数据不被丢失,而closesocket会冒然的抛弃所有的数据,因此如果你愿意closesocket完全可以取代shutdown,然而在数据交互十分复杂的网络协议程序中,最好还是shutdown稳妥一些!?有关TCP协议的连接原理清访问