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

优雅关闭TCP的函数shutdown效果展示

《TCP关闭的两种方法概述》里边理论基础,下边是列出代码,并且进行实验。
服务端代码graceserver.c的内容如下:

#include "lib/common.h"static int count;static void sig_int(int signo) {printf("\nreceived %d datagrams\n", count);exit(0);
}int main(int argc, char **argv) {int listenfd;listenfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in server_addr;bzero(&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htonl(INADDR_ANY);server_addr.sin_port = htons(SERV_PORT);int rt1 = bind(listenfd, (struct sockaddr *) &server_addr, sizeof(server_addr));if (rt1 < 0) {error(1, errno, "bind failed ");}int rt2 = listen(listenfd, LISTENQ);if (rt2 < 0) {error(1, errno, "listen failed ");}signal(SIGINT, sig_int);signal(SIGPIPE, SIG_IGN);int connfd;struct sockaddr_in client_addr;socklen_t client_len = sizeof(client_addr);if ((connfd = accept(listenfd, (struct sockaddr *) &client_addr, &client_len)) < 0) {error(1, errno, "bind failed ");}char message[MAXLINE];count = 0;for (;;) {int n = read(connfd, message, MAXLINE);if (n < 0) {error(1, errno, "error read");} else if (n == 0) {error(1, 0, "client closed \n");}message[n] = 0;printf("received %d bytes: %s\n", n, message);count++;char send_line[MAXLINE];sprintf(send_line, "Hi, %s", message);sleep(5);int write_nc = send(connfd, send_line, strlen(send_line), 0);printf("send bytes: %zu \n", write_nc);if (write_nc < 0) {error(1, errno, "error write");}}
}

客户端代码graceclient.c内容如下:

# include "lib/common.h"
# define    MAXLINE     4096int main(int argc, char **argv) {if (argc != 2) {error(1, 0, "usage: graceclient <IPaddress>");}int socket_fd;socket_fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in server_addr;bzero(&server_addr, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &server_addr.sin_addr);socklen_t server_len = sizeof(server_addr);int connect_rt = connect(socket_fd, (struct sockaddr *) &server_addr, server_len);if (connect_rt < 0) {error(1, errno, "connect failed ");}char send_line[MAXLINE], recv_line[MAXLINE + 1];int n;fd_set readmask;fd_set allreads;FD_ZERO(&allreads);FD_SET(0, &allreads);FD_SET(socket_fd, &allreads);for (;;) {readmask = allreads;int rc = select(socket_fd + 1, &readmask, NULL, NULL, NULL);if (rc <= 0)error(1, errno, "select failed");if (FD_ISSET(socket_fd, &readmask)) {n = read(socket_fd, recv_line, MAXLINE);if (n < 0) {error(1, errno, "read error");} else if (n == 0) {error(1, 0, "server terminated \n");}recv_line[n] = 0;fputs(recv_line, stdout);fputs("\n", stdout);}if (FD_ISSET(0, &readmask)) {if (fgets(send_line, MAXLINE, stdin) != NULL) {if (strncmp(send_line, "shutdown", 8) == 0) {FD_CLR(0, &allreads);if (shutdown(socket_fd, 1)) {error(1, errno, "shutdown failed");}} else if (strncmp(send_line, "close", 5) == 0) {FD_CLR(0, &allreads);if (close(socket_fd)) {error(1, errno, "close failed");}sleep(6);exit(0);} else {int i = strlen(send_line);if (send_line[i - 1] == '\n') {send_line[i - 1] = 0;}printf("now sending %s\n", send_line);size_t rt = write(socket_fd, send_line, strlen(send_line));if (rt < 0) {error(1, errno, "write failed ");}printf("send bytes: %zu \n", rt);}}}}}

代码如上,想要跟我一样编译以后进行测试的话,需要先参考《网络编程实战课程使用Cmake第一次编译程序》进行编译,之后再来验证套接字上的closeshutdown两个函数。

实验一

在其中一个终端,输入./graceserver然后按下一个回车,打开服务器程序。
之后再打开一个终端,输入./graceclient 127.0.0.1然后按下一个回车,打开客户端程序,然后先验证套接字的close函数,快速在5秒内输出data1data2close三个字符串。
在这里插入图片描述
可以看到close函数直接就把客户端套接字的读写两个方向都关闭了。

实验二

在其中一个终端,输入./graceserver然后按下一个回车,打开服务器程序。
之后再打开一个终端,输入./graceclient 127.0.0.1然后按下一个回车,打开客户端程序,然后先验证套接字的close函数,快速在5秒内输出data1data2shutdown三个字符串。
在这里插入图片描述
这里可以看到shutdown只是先把客户端写方向关闭,但是读的方向还打开着,这就是为什么还能接受到服务器端的Hi, data1Hi, data2两个字符串。

此文章为11月Day 11学习笔记,内容来源于极客时间《网络编程实战》。

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

相关文章:

  • 商品管理幻灯图片更换实现
  • tomcat下载与使用教程
  • 通过 Elasticsearch 和 Go 使用混合搜索进行地鼠狩猎
  • 【LIUNX】配置缓存DNS服务
  • Arduino驱动A01NYUB防水超声波传感器(超声波传感器)
  • curl(八)时间和环境变量以及配置
  • K8S知识点(十)
  • Netty实现通信框架
  • 【OpenCV实现图像:用OpenCV图像处理技巧之白平衡算法】
  • 文件包含 [ZJCTF 2019]NiZhuanSiWei1
  • Java网络编程基础内容
  • DevChat:开发者专属的基于IDE插件化编程协助工具
  • Python数据容器之[列表]
  • 大咖直播间”系列直播课第一期——如何抓住HarmonyOS带来的机遇?
  • 跨域:利用JSONP、WebSocket实现跨域访问
  • java项目之戒烟网站(ssm+vue)
  • Redis集群,你真的学会了吗?
  • 手机地磁传感器与常见问题
  • EF Core 数据库映射成实体类
  • 【算法优选】 动态规划之斐波那契数列模型
  • FreeRTOS知识梳理
  • 冒泡排序算法(C++版)
  • 第22章_数据库的设计规范
  • 5. 深度学习——正则化
  • 【链表和顺序表的优缺点】
  • iOS移动应用安全加固:保护您的App免受恶意攻击的重要步骤
  • C# .NET Core API 注入Swagger
  • 家庭安全计划 挑战赛| 溺水预防
  • 飞书开发学习笔记(五)-Python快速开发网页应用
  • 对测试职业发展的思考