《TCP/IP网络编程》(第七章)优雅的断开套接字连接

1.单方断开连接带来的问题

如上图所示,主机A断开连接后,,再也无法接受主机B传输的数据,最终主机B传输的数据只能销毁,为了解决这一问题,再关闭连接时,只关闭流的一部分(半关闭),即可以传输数据但不能接受数据,或者可以接收数据但不能传输数据。

2.套接字的流

两个套接字建立连接后,每个主机拥有单独的输入流和输出流,例如上图左边主机的输出流和右边主机的输入流相连;左边主机的输入流和右边主机的输出流相连。

3.用于半关闭的函数shutdown()

为何需要半关闭?

Linux系统:

  1. 数据传输完成: 当一方已经发送完所有需要发送的数据,但仍然需要接收对方的响应或数据时,可以使用半关闭。这样,发送方可以告诉对方已经没有更多的数据要发送了。
  2. 错误处理: 如果一方在通信过程中遇到错误,它可能会选择关闭发送方向,以防止发送更多的数据,同时仍然监听对方可能发送的错误响应或状态信息。
  3. 保持连接: 在某些应用场景中,即使数据传输已经完成,一方可能仍希望保持连接,以便在将来需要时重新使用,而不是重新建立连接。
  4. 优雅地关闭连接: 在TCP连接中,半关闭允许一方在发送完所有数据后优雅地关闭连接,而不是突然断开,这有助于另一方正确地处理连接的关闭。
  5. 调试和诊断: 在调试网络应用程序时,半关闭可以帮助开发者理解数据流和连接状态,从而更容易地诊断问题。
cpp 复制代码
#include <sys/socket.h>

int shutdown(int sockfd, int how);
//sockfd 是套接字的文件描述符。

//how 指定了关闭的方式,有三种选项:
//SHUT_RD:关闭接收方向,不再接收数据,即断开输入流。
//SHUT_WR:关闭发送方向,不再发送数据,即断开输出流。
//SHUT_RDWR:关闭双向通信,即同时断开输入输出流。

示例代码:

cpp 复制代码
#include <sys/socket.h>
#include <unistd.h>

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字
    // ... 省略了绑定和连接的代码 ...

    // 半关闭套接字,只发送数据,不再接收
    if (shutdown(sockfd, SHUT_WR) == -1) {
        perror("shutdown");
        return 1;
    }

    // 继续发送数据...

    // 最后关闭套接字
    close(sockfd);
    return 0;
}

Windows系统:

cpp 复制代码
#include <winsock2.h>

int shutdown(SOCKET s, int how);
//s 是套接字的句柄。

//how 指定了关闭的方式:
//SD_RECEIVE:关闭接收方向,不再接收数据,即断开输入流。
//SD_SEND:关闭发送方向,不再发送数据,即断开输出流。
//SD_BOTH:关闭双向通信,即同时断开输入输出流。

示例代码:

cpp 复制代码
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

int main() {
    WSADATA wsaData;
    SOCKET sockfd;
    struct sockaddr_in server_addr;

    // 初始化 Winsock
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        return -1;
    }

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    // ... 省略了绑定和连接的代码 ...
    
    // 半关闭套接字,只发送数据,不再接收
    if (shutdown(sockfd, SD_SEND) == SOCKET_ERROR) {
        printf("Shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(sockfd);
        WSACleanup();
        return 1;
    }

    // 继续发送数据...(如果需要的话)

    // 最后关闭套接字
    closesocket(sockfd);

    // 清理 Winsock
    WSACleanup();
    return 0;
}
相关推荐
aixingkong9211 小时前
Nvidia为例 XPU的Multi-Host、Socket Direct 、GPUDirect、RDMA 技术点分析
服务器·网络·硬件架构·硬件工程
今年下半年2 小时前
记录一次IBMS物联网项目的架构设计及技术栈应用
物联网·websocket·网络协议·tcp/ip·微服务·udp·kafka
虎头金猫6 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
wuyk5556 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
XUEYUAN52126 天前
ASN 自治系统号风控:平台如何通过 IP 所属自治域批量识别代理流量
python·网络协议·http·网络安全·socks5
QYRdata6 天前
年均增速24.2%!机器人数据湖未来六年增长动能强劲
网络·机器人·服务发现
CHENKONG_CK6 天前
破解制鞋打磨痛点:RFID赋能去毛刺工序自动化升级
网络·单片机·嵌入式硬件·网络协议·tcp/ip
chshang19926 天前
工业路由器是什么?浅谈5G工业网络中的IR602
网络·物联网·5g·智能路由器
萧瑟余晖6 天前
Netty 核心组件与 Reactor 模型详解
网络·架构
ITxiaobing20236 天前
IP 定位服务选型指南:从准确率到工程落地的技术考察
linux·服务器·网络