当前位置: 首页 > news >正文

《TCP/IP网络编程》阅读笔记--基于 TCP 的半关闭

目录

1--基于TCP的半关闭

1-1--TCP单方面完全断开的问题

1-2--shutdown()函数

1-3--半关闭的必要性

2--基于半关闭的文件传输程序


1--基于TCP的半关闭

1-1--TCP单方面完全断开的问题

        Linux 系统中的 close 函数会将 TCP Socket 的连接完全断开,这意味着不能收发数据(关闭了输入流和输出流),这可能会导致主机 A 无法收到主机 B 的数据(主机A的输入流被关闭了); 

1-2--shutdown()函数

#include <sys/socket.h>
int shutdown(int sock, int howto);
// 成功时返回 0, 失败时返回 -1
// sock 表示需要断开的 Socket 的文件描述符
// howto 表示传递断开的方式信息

        shutdown() 函数可以避免上面完全关闭导致数据丢失的问题,其通过指定断开的方式来选择性地断开输入流、输出流

        断开的方式通过第二个参数来指定,其中 SHUT_RD 表示断开输入流SHUT_WR 表示断开输出流SHUT_RDWR 表示同时断开 I/O 流

1-3--半关闭的必要性

        对于服务器端/客户端的数据传输问题,传输文件的服务器端只需连续传输文件数据即可,但客户端无法知道何时结束数据的接收;

        为了解决上述问题,服务器端应向客户端传递一个 EOF 表示文件传输结束,而客户端通过接收到 EOF 知晓文件传递结束,可以停止接收数据

        断开输出流可以向外传递 EOF(无论是设置 SHUT_WR 还是直接使用 close() 函数);

2--基于半关闭的文件传输程序

服务器端:

// gcc file_server.c -o file_server
// ./file_server 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 30void error_handling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){int serv_sd, clnt_sd;FILE* fp;char buf[BUF_SIZE];int read_cnt;struct sockaddr_in serv_adr, clnt_adr;socklen_t clnt_adr_sz;if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}fp = fopen("file_server.c", "rb");serv_sd = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);serv_adr.sin_port = htons(atoi(argv[1]));bind(serv_sd, (struct sockaddr*)&serv_adr, sizeof(serv_adr));listen(serv_sd, 5);clnt_adr_sz = sizeof(clnt_adr);clnt_sd = accept(serv_sd, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);while(1){read_cnt = fread((void*)buf, 1, BUF_SIZE, fp);if(read_cnt < BUF_SIZE){write(clnt_sd, buf, read_cnt);break;}write(clnt_sd, buf, BUF_SIZE);}shutdown(clnt_sd, SHUT_WR);read(clnt_sd, buf, BUF_SIZE);printf("Message from client: %s \n", buf);fclose(fp);close(clnt_sd);close(serv_sd);return 0;}

客户端:

// gcc file_client.c -o file_client
// ./file_client 127.0.0.1 9190#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 30void error_handling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[]){int sd;FILE* fp;char buf[BUF_SIZE];int read_cnt;struct sockaddr_in serv_adr;if(argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}fp = fopen("receive.dat", "wb");sd = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = inet_addr(argv[1]);serv_adr.sin_port = htons(atoi(argv[2]));connect(sd, (struct sockaddr*)&serv_adr, sizeof(serv_adr));while((read_cnt = read(sd, buf, BUF_SIZE)) != 0){fwrite((void*)buf, 1, read_cnt, fp);}puts("Received file data");write(sd, "Thank you", 10);fclose(fp);close(sd);return 0;
}

运行结果:

http://www.lryc.cn/news/161034.html

相关文章:

  • Rust的模块化
  • vmware设置桥接模式后ip设置
  • 算法通关村第十七关:白银挑战-贪心高频问题
  • 目标检测评估指标mAP:从Precision,Recall,到AP50-95
  • 七大排序算法
  • GitHub two-factor authentication
  • un-app-手机号授权登录-授权框弹不出情况
  • 手写Spring:第14章-自动扫描Bean对象注册
  • redux中间件的简单讲解
  • 嵌入式开发-绪论
  • 大数据知识合集之预处理方法
  • mysql(九)mysql主从复制
  • nodejs采集淘宝、天猫网商品详情数据以及解决_m_h5_tk令牌及sign签名验证(2023-09-09)
  • 虚拟机上部署K8S集群
  • 设计模式 - 责任链
  • 【小沐学Unity3d】3ds Max 骨骼动画制作(CAT、Character Studio、Biped、骨骼对象)
  • CUDA说明和安装[window]
  • sqlserver2012性能优化配置:设置性能相关的服务器参数
  • 介绍 dubbo-go 并在Mac上安装,完成一次自己定义的接口RPC调用
  • 目标检测数据集:摄像头成像吸烟检测数据集(自己标注)
  • Unity的UI管理器
  • Mp4文件提取详细H.264和MP3文件
  • Qt应用程序连接达梦数据库-飞腾PC麒麟V10
  • 2023-09-03 LeetCode每日一题(消灭怪物的最大数量)
  • 绘图 | MATLAB
  • 2023年下半年高项考试学习计划
  • SpringBoot中CommandLineRunner的使用
  • <OpenCV> Mat属性
  • LAMP 综合实验
  • JavaScript发展历程