Chinaunix首页 | 论坛 | 博客
  • 博客访问: 471826
  • 博文数量: 135
  • 博客积分: 1860
  • 博客等级: 上尉
  • 技术积分: 1441
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-05 20:39
文章分类
文章存档

2012年(2)

2011年(130)

2009年(2)

2008年(1)

我的朋友

分类:

2011-08-11 14:56:43

 

从函数调用上来分析(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协议的连接原理清访问

 

Pasted from <>

 

 

TCP有半关闭的情况,如果要全关闭,需要双方向对端发送Fin报文,然后对对方的Find报文进行响应(Ack)

  shutdown表示不再发送数据,但是并没有发送Fin报文,没有终止连接,实际上TCP连接仍然存在,这时如果你要重新建立该Socket对(源/目的端口,源/目的IP均相同)的话是会失败的,因为连接还存在,你就不能重复创建

  如果closesocket后表明连接已经彻底终止了,可以重新用connect/accept建立连接

 

 

closesocket函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构,因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描述符表中的对应表项,并且把s对应的套接字数据结构的引用次数减1。

closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。

 

shutdown():停止  Socket  接收/传送的功能。 

格式:  int  PASCAL  FAR  shutdown(  SOCKET  s,  int  how  ); 

参数:  s  Socket  的识别码,how  代表该停止那些动作的标帜 

传回值:  成功  -  0 

失败  -  SOCKET_ERROR  (呼叫  WSAGetLastError()可得知原因) 

说明:  此函式用来停止  Socket  的後续接收或传送的功能。 

  how  的值为  0,则不再接收资料。 

  how  的值为  1,则不再允许传送资料。 

  how  的值为  2,则不再接收且不再传送资料。 

shutdown()  函式并没有将  Socket  关闭,所以该  Socket  所占用之资源必须在呼叫closesocket()  之後才会释放。

 

如果一个套接字在使用完之后没有CloseSocket,那么端口等资源没有断开,当再利用此端口bind套接字时,bind函数就会出错

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/witchsnk/archive/2008/10/14/3075614.aspx

 

阅读(1382) | 评论(0) | 转发(0) |
0

上一篇:用户登录过程剖析 Bash

下一篇:简述EPOLL

给主人留下些什么吧!~~