Linux socket编程(8):shutdown和close的区别详解及例子

在Linux中有两种操作可以终止socket间的进程通信:closeshutdown。但这两种函数在使用时有着不同的行为和效果。在网络编程中,正确地选择和使用这些操作至关重要,因为它们直接影响着通信的结束和资源的释放。本文将介绍closeshutdown函数,然后举一个实际的例子来说明shutdown的使用。

文章目录

  • 1 close
  • 2 shutdown
  • 3 实例:shutdown的使用
    • 3.1 代码修改
    • 3.2 实验结果
    • 3.3 完整代码

1 close

close函数将终止一个套接字的连接(如果已连接上),然后关闭文件描述符,释放相关的资源。close将关闭数据传输的两个方向,之后进程将无法读/写入套接字。

int close(int sockfd);
  • 参数:
    • sockfd:套接字文件描述符。
  • 返回值:
    • 成功:0
    • 失败:-1,错误号存储于errno中。

注意,close只是将套接字引用计数减一,当引用计数变为零时,真正关闭套接字

  1. 套接字引用计数: 在Linux中,每个打开的套接字都有一个引用计数。引用计数跟踪着对套接字的引用次数,即有多少个文件描述符指向同一个套接字。
  2. close 函数的作用: 当调用close函数关闭一个套接字时,实际上只是将套接字的引用计数减一。这意味着释放了一个对套接字的引用,但套接字仍然存在。

这种机制允许多个进程或线程共享同一个套接字,这个在利用fork实现服务端与多个客户端建立连接中有出现过,使用fork创建子进程的时候,父进程的上下文被拷贝,所以在子进程中的一开始就要close父进程的socket,否则父进程close自身套接字时,套接字并不能真正的被回收。

2 shutdown

shutdown函数用于关闭一个已连接的套接字或禁止在套接字上的发送或接收数据。该函数可以在全双工(TCP)套接字上单独关闭读取或写入,也可以同时关闭两者。

int shutdown(int sockfd, int how);
  • 参数:
    • sockfd:套接字文件描述符。
    • how:关闭方式,可以取值为:
      • SHUT_RD:关闭读取
      • SHUT_WR:关闭写入
      • SHUT_RDWR:同时关闭读取和写入
  • 返回值:
    • 成功:0
    • 失败:-1,错误号存储于 errno 中。

3 实例:shutdown的使用

参考代码上一节的代码IO复用模型之select原理及例子:客户端接收stdin的输入然后发给服务端,服务端收到这个消息后再回显给客户端。

3.1 代码修改

目的:在客户端发送消息给服务端后,等待服务端返回回显数据后,客户端就退出程序。

1、客户端

首先我们希望在标准输入收到EOF时,客户端关闭写方向和标准输入的接收,等待服务端的最后一次回复,收到后打印出来。

在这里插入图片描述

2、服务端

服务端在收到消息后,延时5s,此时在客户端输入EOF,这时客户端关闭掉了写方向。等到延时结束后看看send的回显能不能被客户端收到。

在这里插入图片描述

3.2 实验结果

在这里插入图片描述

这样就实现了客户端发送最后一个消息后,等待服务端回复完后就自动退出程序。

3.3 完整代码

服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024int main() {int serverSocket, clientSockets[MAX_CLIENTS], maxSockets, activity, i, valread;int opt = 1;struct sockaddr_in address;fd_set readfds;char buffer[BUFFER_SIZE];// Create server socketif ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("Socket creation failed");exit(EXIT_FAILURE);}// Set socket optionsif (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {perror("Setsockopt failed");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(8888);// Bind the socketif (bind(serverSocket, (struct sockaddr*)&address, sizeof(address)) < 0) {perror("Bind failed");exit(EXIT_FAILURE);}// Listen for incoming connectionsif (listen(serverSocket, MAX_CLIENTS) < 0) {perror("Listen failed");exit(EXIT_FAILURE);}printf("Server listening on port 8888\n");maxSockets = serverSocket;memset(clientSockets, 0, sizeof(clientSockets));while (1) {FD_ZERO(&readfds);FD_SET(serverSocket, &readfds);for (i = 0; i < MAX_CLIENTS; i++) {int clientSocket = clientSockets[i];if (clientSocket > 0) {FD_SET(clientSocket, &readfds);if (clientSocket > maxSockets) {maxSockets = clientSocket;}}}activity = select(maxSockets + 1, &readfds, NULL, NULL, NULL);if (FD_ISSET(serverSocket, &readfds)) {// Handle new connectionint newSocket;socklen_t addrlen = sizeof(address);if ((newSocket = accept(serverSocket, (struct sockaddr*)&address, &addrlen)) < 0) {perror("Accept failed");exit(EXIT_FAILURE);}printf("New connection, socket fd is %d, ip is : %s, port : %d\n", newSocket, inet_ntoa(address.sin_addr), ntohs(address.sin_port));for (i = 0; i < MAX_CLIENTS; i++) {if (clientSockets[i] == 0) {clientSockets[i] = newSocket;break;}}}for (i = 0; i < MAX_CLIENTS; i++) {int clientSocket = clientSockets[i];if (FD_ISSET(clientSocket, &readfds)) {// Handle data from clientvalread = read(clientSocket, buffer, BUFFER_SIZE);if (valread == 0) {// Client disconnectedprintf("Host disconnected, socket fd is %d\n", clientSocket);close(clientSocket);clientSockets[i] = 0;} else {// Echo received message back to clientbuffer[valread] = '\0';printf("Received: %s", buffer);sleep(5);printf("sleep over\n");send(clientSocket, buffer, strlen(buffer), 0);}}}}return 0;
}

客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUFFER_SIZE 1024int main() {int clientSocket;struct sockaddr_in serverAddress;fd_set readfds;char buffer[BUFFER_SIZE];// Create client socketif ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket creation failed");exit(EXIT_FAILURE);}serverAddress.sin_family = AF_INET;serverAddress.sin_port = htons(8888);serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");// Connect to serverif (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {perror("Connection Failed");exit(EXIT_FAILURE);}printf("Connected to server\n");int stdinOn = 1;while (1) {FD_ZERO(&readfds);if(stdinOn)FD_SET(STDIN_FILENO, &readfds);FD_SET(clientSocket, &readfds);select(clientSocket + 1, &readfds, NULL, NULL, NULL);if (FD_ISSET(STDIN_FILENO, &readfds)) {// Read from stdin and send to serverif(fgets(buffer, BUFFER_SIZE, stdin) == NULL){printf("shutdown\n");shutdown(clientSocket, SHUT_WR);stdinOn = 0;}else{send(clientSocket, buffer, strlen(buffer), 0);}}if (FD_ISSET(clientSocket, &readfds)) {// Read from server and printmemset(buffer, 0, sizeof(buffer));int len = recv(clientSocket, buffer, BUFFER_SIZE, 0);if(len == 0){printf("server close\n");break;}printf("Server: %s", buffer);}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/205704.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Alignment of HMM, CTC and RNN-T,对齐方式详解——语音信号处理学习(三)(选修二)

参考文献&#xff1a; Speech Recognition (option) - Alignment of HMM, CTC and RNN-T哔哩哔哩bilibili 2020 年 3月 新番 李宏毅 人类语言处理 独家笔记 Alignment - 7 - 知乎 (zhihu.com) 本次省略所有引用论文 目录 一、E2E 模型和 CTC、RNN-T 的区别 E2E 模型的思路 C…

mongodb基本操作命令

mongodb快速搭建及使用 1.mongodb安装1.1 docker安装启动mongodb 2.mongo shell常用命令2.1 插入文档2.1.1 插入单个文档2.1.2 插入多个文档2.1.3 用脚本批量插入 2.2 查询文档2.2.1 排序查询2.2.1 分页查询 前言&#xff1a;本篇默认你是对nongodb的基础概念有了了解&#xff…

正则表达式【C#】

1作用&#xff1a; 1文本匹配&#xff08;验证字符串&#xff09; 2查找字符串 2符号&#xff1a; . ^ $ * - ? ( ) [ ] { } \ | [0-9] 匹配出数字 3语法格式&#xff1a; / 表示模式 / 修饰符 /[0-9]/g 表示模式&#xff1a;是指匹配条件&#xff0c;要写在2个斜…

【LabVIEW学习】3.labview制作安装程序

一。生成exe文件 1.创建可执行文件 &#xff08;1&#xff09;创建项目 注意&#xff1a; 1.创建.exe文件&#xff0c;这个文件在labview环境下才可以运行&#xff0c;如果直接传递给其他电脑&#xff08;没有labview环境&#xff09;&#xff0c;他是不可以运行的。 2.如果已…

Redis-Redis 高级数据结构 HyperLogLog与事务

Redis 高级数据结构 HyperLogLog HyperLogLog(Hyper [ˈhaɪpə(r)] ) 并不是一种新的数据结构 ( 实际类型为字符串类 型) &#xff0c;而是一种基数算法 , 通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是 IP 、 Email 、 ID 等。 如…

最大熵模型

1. 最大熵原理 学习概率模型时&#xff0c;在所有可能的概率模型(分布)中&#xff0c;熵最大的模型是最好的模型。 假设离散随机变量X的概率分布是P(X)&#xff0c;则其熵为 且满足0<H(P)<logN 当且仅当X的分布是均匀分布时右边的等号成立&#xff0c;即当X服从均匀分布…

48、Flink DataStream API 编程指南(1)- DataStream 入门示例

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

新材料制造ERP用哪个好?企业应当如何挑选适用的

有些新材料存在特殊性&#xff0c;并且在制造过程中对车间、设备、工艺、人员等方面提出更高的要求。还有些新材料加工流程复杂&#xff0c;涉及多种材料的请购、出入库、使用和管理等环节&#xff0c;解决各个业务环节无缝衔接问题是很多制造企业面临的管理难题。 新材料制造…

CSS3样式详解之圆角、阴影及变形

目录 前言一、圆角样式&#xff08;border-radius&#xff09;二、元素阴影&#xff08;box-shadow&#xff09;三、过渡动画样式&#xff08;transition&#xff09;1. transition-property(用于设置属性名称)2. transition-duration&#xff08;设置时间&#xff09;3. trans…

unity UI特效遮罩

using System.Collections; using System.Collections.Generic; using UnityEngine;/**UI特效遮罩 1.需要将ScrollRect 的遮罩Mask 换为 2D Mask2.将特效的Render里面的 Masking 设置为*/ public class UIParticleMaskControll : MonoBehaviour {// Start is called before …

Spring Cloud Stream如何屏蔽不同MQ带来的差异性?

引言 在当前的微服务架构下&#xff0c;使用消息队列&#xff08;MQ&#xff09;技术是实现服务解耦和削峰填谷的重要策略。为了保证系统的灵活性和可替换性&#xff0c;我们需要避免对单一开源技术的依赖。 市面上有多种消息队列技术&#xff0c;如 Kafka、RocketMQ、Rabbit…

uniapp2023年微信小程序头像+昵称分别获取

1、DOM <view class"m-user"><view class"user-info"><!--头像 GO--><button class"avatar avatar-wrapper" open-type"chooseAvatar" chooseavatar"onChooseAvatar"slot"right"><im…

智能手表上的音频(四):语音通话

上篇讲了智能手表上音频文件播放。本篇开始讲语音通话。同音频播放一样有两种case&#xff1a;内置codec和BT。先看这两种case下audio data path&#xff0c;分别如下图&#xff1a; 内置codec下的语音通话audio data path 蓝牙下的语音通话audio data path 从上面两张图可以看…

数字化时代的政务服务:构建便捷高效的线上政务大厅

引言&#xff1a; 随着数字化时代的来临&#xff0c;如何通过线上政务大厅搭建一个便捷高效的服务平台&#xff0c;以更好地满足公众需求值得探究。线上政务大厅是政务服务的新方式&#xff0c;但搭建线上政务大厅并不是一件容易的事情&#xff0c;需要精心的规划和设计。 一…

linux 应用开发笔记---【I/O文件/基础篇 】

文章笔记来自于【速学Linux】手把手教你学嵌入式Linux C应用编程_哔哩哔哩_bilibili 一&#xff0c;什么是linux应用程序 1.运行在linux操作系统用户空间的程序 2.内核程序运行在内核空间&#xff0c;应用程序运行在用户空间 在终端执行的命令ls,ps。。。。。。都是运行在用…

vue3实现元素拖拽移动功能

效果图 实现拖拽移动 首先我们给需要实现功能的元素加一个draggable"true"让元素能够被拖拽 先来认识两个搭配draggable属性一起使用的事件——ondragstart和ondragend&#xff0c;它们的定义分别为&#xff1a; ①. ondragstart 事件在用户开始拖动元素或选择的文…

BUUCTF [GXYCTF2019]BabyUpload 1详解(.htaccess配置文件特性)

题目环境&#xff1a;查看题目源码 SetHandler application/x-httpd-php 通过源码可以看出这道文件上传题目主要还是考察.htaccess配置文件的特性 倘若不先上传.htaccess配置文件&#xff0c;那么后台服务器就无法解析php代码 这个是需要注意的 .htaccess配置文件特性 概述来说…

python爬虫AES案例:某招聘网站

声明&#xff1a; 该文章为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;违者后果自负&#xff0c;由此产生的一切后果均与作者无关 一、找出需要加密的参数 js运行 atob(‘aHR0cHM6Ly93d3cua2Fuemh1bi5jb20vc2VhcmNoLz9xdWVyeT1weXRob24mdHlwZT0w’) 拿到网址…

基于Java web的多功能游戏大厅系统的开发与实现

摘 要 目前&#xff0c;国内游戏市场上的网络游戏有许多种类&#xff0c;游戏在玩法上也越来越雷同&#xff0c;形式越来越单调。这种游戏性系统给玩家带来的成就感虽然是无穷的&#xff0c;但是也有随之而来的疲惫感&#xff0c;尤其是需要花费大量的时间和精力&#xff0c;这…

【Docker】从零开始:8.Docker命令:Commit提交命令

【Docker】从零开始&#xff1a;8.Docker命令:Commit命令 基本概念镜像镜像分层什么是镜像分层为什么 Docker 镜像要采用这种分层结构 本章要点commit 命令命令格式docker commit 操作参数实例演示1.下载一个新的ubuntu镜像2.运行容器3.查看并安装vim4.退出容器5提交自己的镜像…