VS2015中Winsock编程之优雅关闭套接字

1 优雅关闭套接字简介

《VS2015套接字编程断开套接字连接》中提到,可以使用shutdown()、closesocket()和WSACleanup()三个函数组合在一起关闭已经连接的套接字。在关闭套接字时,对于流套接字,可能会在数据队列中还存在未发送的数据,在关闭套接字之后,对端将无法接收到这些数据。优雅关闭套接字的作用是,当关闭套接字之前,将数据队列中还未发送的数据发送给对方,再关闭套接字。

《VS2015中基于TCP客户端的实现》《VS2015中基于TCP/IP的服务端的实现》中提到了基于TCP/IP通信的客户端和服务端的流程。服务端创建套接字、绑定套接字、设置套接字的监听模式并等待客户端的连接。而客户端创建套接字之后,就通过该套接字连接服务端,服务端在接收了客户端的连接之后,创建一个新的套接字,并使用while()循环接收来自客户端的数据,客户端向服务端发送数据,服务端接收数据并处理,之后再次等待客户端数据的到来。

优雅关闭套接字就是基于以上前提的,此时客户端的数据已经发送完毕,而服务端正处于while()循环中,等待服务端发送数据,而此时服务端也有可能向客户端发送数据。在服务端发送数据完毕后,要断开套接字时,应当考虑此时服务端是否有数据正向自己发送,所以要使用优雅断开套接字的方式来解决这个问题。

2 优雅关闭套接字的具体流程

图1 优雅关闭套接字流程框图

在图1中,红色表示客户端,黑色表示服务端。由客户端首先通过shutdown()关闭本端的发送功能,此时服务端会收到FD_CLOSE指令(该指令由系统内核处理,服务端代码无需关系),服务端的recv()函数返回值为0,此时服务端知道客户端已经关闭了发送数据的功能,则退出while()循环。而客户端在通过shutdown()关闭本端的发送功能后,为了能接收到服务端还未来得及发送的数据,需要通过while()循环接收来自服务端的数据。而服务端在退出了while()循环之后,通过shutdown()关闭本端的发送功能,此时客户端会收到FD_CLOSE指令,说明服务端的数据已经发送完毕,则客户端退出while()循环。这样,服务端和客户端在套接字被断开之前都可以完全收到了对端的数据,实现了套接字的优雅关闭。最后,双方调用closesocket()函数和WSACleanup()函数,关闭套接字和释放Winsock动态库资源。

3相关代码

3.1 客户端代码

iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)

{

closesocket(ConnectSocket);

    WSACleanup();

return 1;

}

do {

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

} while( iResult > 0 );

closesocket(ConnectSocket);

WSACleanup();

在以上代码中,ConnectSocket是客户端与服务端通信的套接字,SD_SEND表示shutdwon()函数关闭了套接字的发送功能,recvbuf用于保存从服务端中接收到的数据。

3.2 服务端代码

do {

iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);

} while (iResult > 0);

iResult = shutdown(ClientSocket, SD_SEND);

if (iResult == SOCKET_ERROR)

{

   closesocket(ClientSocket);

   WSACleanup();

return 1;

 }

closesocket(ClientSocket);

WSACleanup();

在以上代码中ClientSocket是服务端用于与客户端通信的套接字。

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值