22-LINUX--多线程and多进程TCP连接

一.TCP连接基础知识

1.套接字

        所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口  

套接字 = IP + 端口

知名端口:1024以内的端口,不能随便用

保留端口:1024-4096

2.检查服务器端与客户端之间是否正常连接

查看发送缓冲区,接收缓冲区未被接收或读取的信息

netstat   -natp

3.TCP的特点

面向连接的,可靠的,流式服务

TCP的特点如何保证:tcp具有应答确认,超市重传机制,乱序重排,去重,滑动窗口进行流量控制

4.粘包

多个数据包被连续存储于连续的缓冲区中,在对数据包进行读取时无法缺点数据包之间的边界;

解决方法:1.加标记2.自己设计包头描述数据部分的大小

二.多线程TCP网络连接

ser.c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>int socket_init();void* thread_fun(void* arg)
{int *p=(int*)arg;if(p==NULL)//传进来指针,必须判空{pthread_exit(NULL);}int c = *p;free(p);while(1){char buff[128]={0};int n=recv(c,buff,127,0);//-1失败 0对方关闭连接if(n <=0){break;}printf("buff(%d)=%s\n",c,buff);send(c,"ok",2,0);}printf("buff(%d) close\n",c);close(c);pthread_exit(NULL);
}int main()
{int sockfd =socket_init();if(sockfd ==-1){exit(1);}while(1){int c = accept(sockfd,NULL,NULL);//c与用户交互的关键值if(c<0){continue;}printf("accept c =%d\n",c);pthread_t id;int* p =(int*)malloc(sizeof(int));*p = c;pthread_create(&id,NULL,thread_fun,(void*)p);}
}
int socket_init()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){return -1;}struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res==-1){printf("bind err\n");return -1;}res = listen(sockfd,5);if(res ==-1){return -1;}return sockfd;
}89,1         底端

上述ser.c代码中,在客户端退出连接后,没有回收子线程的空间,通常需要使用pthread_join回收空间,但是这样会无法使客户端同时连接服务器,所以使用下列改进代码,在关闭连接时,即可回收空间,无需使用join.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>int socket_init();void* thread_fun(void* arg)
{int *p=(int*)arg;if(p==NULL)//传进来指针,必须判空{pthread_exit(NULL);}int c = *p;free(p);while(1){char buff[128]={0};int n=recv(c,buff,127,0);//-1失败 0对方关闭连接if(n <=0){break;}printf("buff(%d)=%s\n",c,buff);send(c,"ok",2,0);}printf("buff(%d) close\n",c);close(c);pthread_exit(NULL);
}
nt main()
{int sockfd =socket_init();if(sockfd ==-1){exit(1);}while(1){int c = accept(sockfd,NULL,NULL);//c与用户交互的关键值if(c<0){continue;}printf("accept c =%d\n",c);pthread_t id;pthread_attr_t attr;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);//设>置脱离属性,不需要执行joinint* p =(int*)malloc(sizeof(int));*p = c;pthread_create(&id,NULL,&attr,thread_fun,(void*)p);}
}
int socket_init()
{int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){return -1;}struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res==-1){printf("bind err\n");return -1;}res = listen(sockfd,5);if(res ==-1){return -1;}return sockfd;
}92,1         底端

cli.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){exit(1);}struct sockaddr_in saddr;//代表服务器的端口memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res == -1){printf("connct err\n");exit(1);}while(1){printf("input: ");char buff[128]={0};fgets(buff,128,stdin);if(strncmp(buff,"end",3)==0){break;}send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf("buff=%s\n",buff);}close(sockfd);exit(0);
}

三.TCP多进程连接

ser.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<pthread.h>
#include<assert.h>
#include<signal.h>
#include<sys/wait.h>
void fun(int sig)
{wait(NULL);
}
int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);//tcp if(sockfd ==-1){exit(1);}struct sockaddr_in saddr,caddr; // saddr-ser  caddr-climemset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr =inet_addr("127.0.0.1");int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res == -1){printf("bind err\n");exit(1);}listen(sockfd,5);signal(SIGCHLD,fun);
//signal(SIGCHLD,SIG_IGN);//LINUX系统处理僵死进程特有的方法while(1){int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);if(c<0){continue;}printf("accept c =%d\n",c);pid_t pid = fork();assert(pid != -1);if(pid == 0){close(sockfd);//子进程不需要sockfdwhile(1){char buff[128] = {0};int n=recv(c,buff,127,0);if(n<=0){break;}printf("recv(%d)=%s\n",c,buff);send(c,"ok",2,0);}close(c);printf("client(%d) close\n",c);exit(0);}close(c);//父进程关闭连接,c引用计数减1}
}int socket_init()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd ==-1){return -1;}struct sockaddr_in saddr,caddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("137.0.0.1");int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res == -1){return -1;}listen(sockfd,5);return sockfd;
}96,1         底端

cli.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){exit(1);}struct sockaddr_in saddr;//代表服务器的端口memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res == -1){printf("connct err\n");exit(1);}while(1){printf("input: ");char buff[128]={0};fgets(buff,128,stdin);if(strncmp(buff,"end",3)==0){break;}send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf("buff=%s\n",buff);}close(sockfd);exit(0);
}

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

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

相关文章

Python编程入门:从零开始掌握基础

Python编程入门:从零开始掌握基础 Python是一门简单易学但功能强大的编程语言。它广泛应用于数据科学、机器学习、web开发、自动化任务等领域。本系列文章将带你从零开始学习Python,逐步掌握这门语言的基础知识。本文是系列的第一篇,涵盖Python的基本语法、变量和数据类型等…

GitLab的原理及应用详解(七)

本系列文章简介: 随着软件开发的不断进步和发展,版本控制系统成为了现代软件开发过程中不可或缺的一部分。而GitLab作为其中一种流行的版本控制工具,在软件开发领域享有广泛的应用。GitLab不仅提供了强大的版本控制功能,还集成了项目管理、持续集成和部署、代码审查等多个功…

蓝卓supOS工业操作系统应用场景

supOS是国内首个自主知识产权的工业操作系统&#xff0c;也是首个以自动化技术为起点&#xff0c;从下至上推进的开放的以企业为核心的工业互联网平台、工业大数据平台、工业人工智能平台。以工厂全信息集成为突破口&#xff0c;实现生产控制、生产管理、企业经营等多维、多元数…

React 中Redux结合React-Redux使用类组件版本(一)

一、Redux是什么&#xff1f; 1.Redux是一个专门用于状态管理的js库 2.它可以用在React、Angular、Vue的项目中&#xff0c;但基本与React配合使用。 3.作用&#xff1a;集中式管理React应用中多个组件共享的状态。 二、Redux 工作流程 三、Redux的三个核心概念 1.action 动…

振弦采集仪在岩土工程监测中的精度与可靠性评估

振弦采集仪在岩土工程监测中的精度与可靠性评估 河北稳控科技振弦采集仪是一种常用的岩土工程土体力学参数监测仪器&#xff0c;它主要用于测量岩土中的应力、应变和模量等力学参数。在岩土工程中&#xff0c;土体力学参数的精确测量对于工程设计、施工和监测都非常重要。因此…

前缀和算法专题

应用: 计算数组中某区间的和 一. 一维前缀和[模版] 答案 二. 二维前缀和[模版] 答案 三. 寻找数组的中心下标 答案 四. 除自身以外数组的乘积 答案 五. 和为k的子数组 答案 六. 和可被k整除的子数组 答案 七. 连续数组 答案 八. 矩阵区域和 答案

如何查看网站的cookie?

前言&#xff1a; 在网络世界中&#xff0c;cookie是一种常见的信息存储方式。 对于开发者和普通用户来说&#xff0c;了解如何查看CSDN的cookie是非常重要的。 本文将介绍几种常用的方法&#xff0c;帮助大家更好地理解和使用cookie&#xff1a; 代码示例&#xff1a; 通过浏…

vue 自定义事件总线类进行组件间通信

写一个eventBus.js&#xff1a; export default class eventBus{constructor() {this.events {};}on(eventName, callback) {if (typeof callback ! "function") {throw "请传入监听函数";}if (!this.events[eventName]) {this.events[eventName] [];}t…

Docker基础篇之入门使用

文章目录 1. Docker的基本组成2. Docker平台架构3. 阿里云镜像加速4. Docker的Hello World入门案例5. 总结 1. Docker的基本组成 Docker的基本组成主要是有四部分&#xff0c;分别是镜像、容器和仓库。 镜像&#xff1a;Docker镜像就是一个只读的模版&#xff0c;镜像可以用来…

【Spring】深入理解 Spring 状态机:简化复杂业务逻辑的利器

前言 在软件开发中&#xff0c;有许多场景需要处理状态转换和状态驱动的逻辑&#xff0c;比如订单处理、工作流程管理、游戏引擎等。Spring 状态机&#xff08;Spring State Machine&#xff09;是 Spring Framework 提供的一个强大的模块&#xff0c;用于帮助开发人员轻松构建…

二叉搜索树BST ——(C++)

本篇将会讲解有关二叉树的搜索原理&#xff0c;以及关于二叉搜索树的建立&#xff0c;以及二叉树搜索树的插入、删除和查找等基本操作。最后我们还会对二叉搜索树进行功能扩展&#xff0c;介绍有关搜索二叉树的 K 模型和 KV 模型。目录如下&#xff1a; 目录 1. 搜索二叉树 二叉…

前端学习CSS-2

盒子模型 盒子模型相关属性 一些盒子模型的样式示例 传统网页布局方式 浮动 浮动的三大特性 脱标&#xff1a;脱离标准流一行显示&#xff0c;顶部对齐具备行内块元素特性 定位

Java整合EasyExcel实战——1

参考&#xff1a;读Excel | Easy Excel快速使用easyexcel的来完成excel的读取https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read 准备条件 依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifa…

Android 动效整理

Android自定义SeekBar&#xff0c;滑动时弹出气泡指示器显示进度 安卓开发中非常炫的效果集合_android 开发 向右上角收起炫酷动态效果-CSDN博客 https://github.com/shenghuntianlang/Android-Views?tabreadme-ov-file#decentbanner 以前收藏了很多文章&#xff0c;但是过…

【UE5.1 角色练习】08-传送技能

前言 在上一篇&#xff08;【UE5.1 角色练习】07-AOE技能&#xff09;基础上继续实现人物通过鼠标点击然后传送技能的功能。 效果 步骤 1. 首先需要显示鼠标光标&#xff0c;我们可以在玩家控制器中勾选“显示鼠标光标” 2. 在项目设置中添加一个操作映射&#xff0c;设置按…

Python爬虫入门实例:Python7个爬虫小案例(附源码)

引言 随着互联网的快速发展&#xff0c;数据成为了新时代的石油。Python作为一种高效、易学的编程语言&#xff0c;在数据采集领域有着广泛的应用。本文将详细讲解Python爬虫的原理、常用库以及实战案例&#xff0c;帮助读者掌握爬虫技能。 一、爬虫原理 爬虫&#xff0c;又…

Vue3.0 里为什么要用 Proxy API替代 defineProperty API?

Vue3.0选择使用Proxy API替代defineProperty API的原因主要有以下几点&#xff1a; 性能提升&#xff1a; Proxy API允许拦截整个对象&#xff0c;而defineProperty API需要遍历对象的每个属性进行拦截。因此&#xff0c;Proxy API在捕获对象的访问和修改时更为高效。 更全面的…

maptr(2):论文及代码解读

文章目录 1. 介绍2. 模型架构2.1 GT 数据制作2.2 模型架构2.3 GKT2.3.1 cross attn 的变化2.3.1 GKT2.4 decoder部分2.5 header2.5.1 reg_branch2.5.2 cls_branch3. Loss计算3.1 正负样本匹配3.2 loss计算<