高并发服务器-多进程

B站就业班视频-对应52课

28_哔哩哔哩_bilibili

上一篇文章,如果再多开一个终端(客户端),发送小写字母,想转换成大写,就没有反应了,关闭这个客户端,服务器也没有丝毫反应,说明上篇代码只能1对1 ,这是不现实的,所以这节课来讲如何实现多个客户端同时访问服务端,服务端能挨个回信息。

原因:

由于accept 和read函数都会阻塞,如当read的时候,不能调用accept接受新的连接,当accept阻塞等待的时候,不能read读数据。

注意,这篇代码只是服务端的,客户端代码跟我昨天文里一样

1.基础思路

socket()创建套接字

bind 将套接字文件描述符,和本地一个IP 端口联系在一起

listen

accept()创建一个连接描述符,一般阻塞在这里;;等待;;

fork () 父进程关闭上述描述符   子进程关闭套接字文件描述符

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>//将网络大端模式的地址,转化为字符串
//const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);int main() {int sfd = socket(AF_INET, SOCK_STREAM, 0);if (sfd <0){printf("socket fun error/n");return -1;}//定义一个地址结gou体struct sockaddr_in myad;//清空  memorybzero(&myad, sizeof(myad));myad.sin_family =AF_INET;myad.sin_port =htons(8888);myad.sin_addr.s_addr = htonl (INADDR_ANY);int ret = bind(sfd, (struct sockaddr *)&myad, sizeof(myad));if (ret<0) {printf("bind error/n");return -1;}//将socket从主动变为被动(服务器必备),这样可以监听来自客户的请求listen( sfd,128);   // int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//addr是传出参数,保留客户的地址,所以这是客户地址//定义一个地址结gou体接受客户端地址结构体struct sockaddr_in dst;bzero(&myad, sizeof(myad));dst.sin_family =AF_INET;dst.sin_port =htons(8888);socklen_t dstleng = sizeof(dst);while (1) {//jieshou client connect int newfd = accept (sfd, (struct sockaddr* )&dst, &dstleng);if (newfd <0) {printf("服务端,accept error、\n");return -1;}char addstring[128];memset(addstring, 0x00,128);printf("服务器端,还没有fork,客户端地址是:\n");printf("IP:%s,PORT: %d\n", inet_ntop(AF_INET, &dst.sin_addr.s_addr,addstring,sizeof(addstring)),ntohs(dst.sin_port));//fork  child tackle message, father listenpid_t clientpid;clientpid = fork();if( clientpid<0) {printf("fork error\n");return -1;}else if (clientpid>0){//father process ,close message 文件描述符close (newfd);}else if (clientpid ==0){//子进程,打印端口,发现一个子进程1个端口,当然ip共享 printf("child process,IP:%s,PORT: %d\n", inet_ntop(AF_INET, &dst.sin_addr.s_addr,addstring,sizeof(addstring)),ntohs(dst.sin_port));//把客户端发送过来的数据读出来int i =0;int n =0;char buf[1024];while (1){memset(buf,0x00,sizeof(buf));n = read (newfd,buf,sizeof(buf));if (n<=0){printf("有一个客户端已关闭,或者读到的字符为0/n");break;}for (i=0;i<n;i++){buf[i] =toupper(buf[i]);}//把数据传回客户端,变成大写了已经write (newfd, buf, n);}close(newfd);exit(0); //子进程退出,避免再次fork子进程}}
close (sfd);//这行是自己写的,老师有没有这行没看清.
return 0;
}

注意,其实这里面很多函数老师用的是封装过的,,我这里还是写的原始函数 

2.本节课其他知识点 

(在CSDN上搜索相应知识点自学)

2.1 TCP连接时的 3次握手和4次挥手过程,并且写出其中的数字

2.2 TCP数据格式,IP数据格式

2.3 流量控制

当接受和发送的速度不匹配的时候,(例如:fast sender, slow receiver)解决方案(有很多),着重讲解(滑动窗口)

当socket编程中,我们调用read write函数的时候,是从内核的缓冲区中调集数据,一个是发送缓冲区,另一个是接受缓冲区,被同一个fd(文件描述符)所控制。

2.4 mss 和MTU

MTU:最大传输单元,通信术语,Maximum Transmission Unit,  是指一种通信协议的某一层上面能通过的最大数据包大小(以字节为单位)。最大传输单元这个参数通常与通信接口有关(网络接口卡,串口等),这个值如果设置为太大会导致丢包重传的时候重传的数据量较大,图中的最大值是1500,其实是一个经验值。

mss :最大报文长度,只是在建立连接的时候,告诉对方我最大能够接收多少数据,在数据通信的过程中就没有mss了

2.5封装函数

封装函数的优点 --节省重复代码

在封装函数的时候,返回值是-1的时候表示失败了。

errno宏:可以用 man errno(命令)来查询宏名称和对应编号,例如

ECHILD          No child processes (POSIX.1-2001).

2.6 errno

老师的讲义,和许多其他文章说,在/usr/include/asm-generic/errno.h文件中包含了所有的编号。但是我cat errno.h 只有一堆注释和以下内容——

#ifndef _ERRNO_H

#define _ERRNO_H 1

#include <features.h>

/* The system-specific definitions of the E* constants, as macros.  */

#include <bits/errno.h>

/* When included from assembly language, this header only provides the

   E* constants.  */

#ifndef __ASSEMBLER__

__BEGIN_DECLS

/* The error code set by various library functions.  */

extern int *__errno_location (void) __THROW __attribute_const__;

# define errno (*__errno_location ())

# ifdef __USE_GNU

/* The full and simple forms of the name with which the program was

   invoked.  These variables are set up automatically at startup based on

   the value of argv[0].  */

extern char *program_invocation_name;

extern char *program_invocation_short_name;

#include <bits/types/error_t.h>

# endif /* __USE_GNU */

__END_DECLS

#endif /* !__ASSEMBLER__ */

#endif /* errno.h */)

关于socket编程中,忽略以下两种情况的errno,不认为是失败,而是返回循环,继续尝试

    1. errno =EINTR

像accept ,read这样能够引起阻塞的函数,若被信号打断,由于信号的优先级较高,会优先处理信号,等信号处理完成后,会使accept 或者read解除阻塞,然后返回,此时返回值是-1,设置errno =EINTR

    1. errno = ECONNABORTED

表示连接被打断

***********   ************************   *************

以下块引用内容来自CSDN博客,博主iteye_5425的《几个常见的 Socket 连接错误及原因》

ECONNABORTED

     该错误被描述为“software caused connection abort”,即“软件引起的连接中止”。原因在于当服务和客户进程在完成用于 TCP 连接的“三次握手”后,客户 TCP 却发送了一个 RST (复位)分节,在服务进程看来,就在该连接已由 TCP 排队,等着服务进程调用 accept 的时候 RST 却到达了。POSIX 规定此时的 errno 值必须 ECONNABORTED。源自 Berkeley 的实现完全在内核中处理中止的连接,服务进程将永远不知道该中止的发生。服务器进程一般可以忽略该错误,直接再次调用accept。/* Linux system */

include/asm-alpha/errno.h:#define ECONNABORTED 53 /* Software caused connection

abort */

include/asm-generic/errno.h:#define ECONNABORTED 103 /* Software caused

connection abort */

include/asm-mips/errno.h:#define ECONNABORTED 130 /* Software caused connection

abort */

***********   ************************   *************

2.7 粘包问题

多次发送,接收端不能分辨第一次发送多少,第二次发送多少。例如:第一次发送30个,第二次发送10个,接受的时候每次最多接20个,那么第一次剩下10个就在第二次接受了。

解决方案

(1)报头+数据

报头设置为4字节,报头里写明了数据长度,这样read函数跳过4字节之后,就知道后面要读多少了,避免了粘包问题。

(2)添加结尾标记。但是需要双方协商,还需要挨个去判断。

(3)数据包定长。例如,约定每个包就是128字节。

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

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

相关文章

Spring Boot入门

SpringBoot介绍 什么是SpringBoot Spring Boot是由Pivotal团队提供的全新框架&#xff0c;其中“Boot”的意思就是“引导”&#xff0c;Spring Boot 并不是对 Spring 功能上的增强&#xff0c;而是提供了一种快速开发 Spring应用的方式。 特点 • 嵌入的 Tomcat&#xff0c…

01 SpringBoot3快速入门

本次使用3.0.5版本 SpringBoot整合了之前的一切。 需求&#xff1a;浏览器发送/hello请求&#xff0c;返回"Hello,Spring Boot 3!" 总体开发步骤&#xff1a; 1. 创建Maven工程 2. 添加依赖(springboot父工程依赖 , web启动器依赖) 3. 编写启动引导类(springboot项…

速通——决策树(泰坦尼克号乘客生存预测案例)

一、决策树 1、概述 树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果 2、建立过程 1. 特征选择&#xff1a;选取有较强分类能力的特征。 2. 决策树生成&#xff1a;根据选择的特征生成决策树。 3.…

Gazebo的模型下载。

git clone zouxu634866/gazebo_modelshttps://gitee.com/zouxu6348660/gazebo_models.git&#xff0c;并完成路径配置。 &#xff08;本文提供了gitee下载&#xff0c;国外的Github下载较慢。&#xff09;

芯课堂 | 华芯微特MCU在PCB板级设计中对ISP引脚的应用

1.应用描述 ISP&#xff08;In System Programming&#xff09;&#xff0c;在系统编程&#xff0c;使用片内驻留出厂引导程序&#xff08;BootROM&#xff09;配合UART / SPI等外设进行烧录。 华芯微特全系MCU的ISP操作说明&#xff1a;当芯片上电后检测到 ISP 引脚持续 5ms…

openssl3.2 - xx_fetch函数参数名称字符串有效值列表

文章目录 openssl3.2 - xx_fetch函数参数名称字符串有效值列表概述笔记xx_fetch函数所在的头文件目录xx_fetch函数所在的头文件列表xx_fetch函数列表每个xx_fetch()API的字符串名称的有效值列表OSSL_DECODER *OSSL_DECODER_fetch();OSSL_ENCODER *OSSL_ENCODER_fetch();EVP_CIP…

LLaMa2 Chat gpt 大模型本地部署初体验

一直想在自己电脑或者测试环境随便找台服务器尝试部署一下“大模型”&#xff0c;但“大模型”对于内存和GPU的要求令人望而却步&#xff0c;层出不穷的各种术语也令人困惑&#xff0c;有点难以下手。 经过一段时间&#xff0c;在百度千帆大模型平台、讯飞星火大模型平台、魔搭…

贪心算法part04 算法

贪心算法part04 算法 ● 860.柠檬水找零 ● 406.根据身高重建队列 ● 452. 用最少数量的箭引爆气球 1.leetcode 860.柠檬水找零 https://leetcode.cn/problems/lemonade-change/description/ class Solution {public boolean lemonadeChange(int[] bills) {//看能不能找零/…

【数据结构】哈希表详解,举例说明 java中的 HashMap、HashTable及其区别

一、哈希表&#xff08;Hash Table&#xff09;简介&#xff1a; 哈希表是一种数据结构&#xff0c;用于实现字典或映射等抽象数据类型。它通过把关键字映射到表中的一个位置来实现快速的数据检索。哈希表的基本思想是利用哈希函数将关键字映射到数组的索引位置上&#xff0c;…

【征服redis2】redis的事务与lua

1.redis事务介绍 在前面我们介绍了redis的几种典型数据结构和应用&#xff0c;本文我们来看一下redis的事务问题。事务也是数据库的重要主题&#xff0c;熟悉关系型数据库的读者应该对事务比较了解&#xff0c;简单地说&#xff0c;事务表示一组动作&#xff0c;要么全部执行&…

Python 实现快速排序的代码

使用 Python 实现快速排序的代码&#xff1a; python def quicksort(arr): if len(arr) < 1: return arr pivot arr[len(arr) // 2] left [x for x in arr if x < pivot] middle [x for x in arr if x pivot] right [x for x in arr if x > pivot] retu…

esp32-idf Eclipse Log日志打印demo

Log日志打印demo 1、代码例程 esp32-S2 芯片 / Eclipse软件 开发环境 #include <stdio.h> #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_…

【linux】终端发送网络请求与文件下载

发送网络请求 linux的终端中发送网络请求可以使用curl命令。 语法&#xff1a; curl [url] 但是他返回的是html代码&#xff0c;因为在终端中&#xff0c;他无法像浏览器中一样把访问到的html代码渲染成我们访问的页面&#xff0c;所以我们只能拿到他的源码。 访问CSDN - 专…

1.机器学习-机器学习算法分类概述

机器学习-机器学习算法分类概述 个人简介机器学习算法分类&#xff1a;监督学习、无监督学习、强化学习一监督学习1. 监督学习分类任务举例&#xff1a;1.1 特征1.2 标签 二无监督学习1.关键特点2.应用示例3.常见的无监督学习算法 三强化学习1.定义2.示例场景 四机器学习开发流…

数据结构之串|数组|广义表

串 数组 广义表 总结&#xff1a;

2021-05-31 git操作

Git 多人协作开发的过程 Git可以完成两件事情&#xff1a; 版本控制 2.多人协作开发 如今的项目&#xff0c;规模越来越大&#xff0c;功能越来越多&#xff0c;需要有一个团队进行开发。 如果有多个开发人员共同开发一个项目&#xff0c;如何进行协作的呢。 Git提供了一个…

【加强版】小学数学出题,加减乘除混合运算,支持自定义数字,一键打印

在线预览&#xff1a;在线HTML代码预览和运行工具 - UU在线工具 复制下面代码后到该地址预览即可 注意&#xff1a;在线预览不能打印。如需打印&#xff0c;在电脑本地上新建文本文档&#xff0c;粘贴代码后保存&#xff0c;然后把文件后缀改为.html运行&#xff0c;出题点击…

haiku实现三角乘法模块

三角乘法&#xff08;TriangleMultiplication&#xff09;是作为一种更对称、更便宜的三角注意力&#xff08;TriangleAttention&#xff09;替代模块。 import jax import haiku import jax.numpy as jnpdef _layer_norm(axis-1, namelayer_norm):return common_modules.Laye…

【CF闯关练习】—— 1400分(C. Make Good、B. Applejack and Storages)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;cf闯关练习 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

isis小实验

要求: 1.合理规划level1-2 2.r1访问r5走r6且走上面 3.全网可达 个人理解:以重发布的视角:is-level level1即L1可以看做rip,L2可以看做OSPF,L1-2可以看作是既要rip又要OSPF,优点:isis只用在每个路由器上宣告一次 缺点:isis需要每个接口上输isis enable 1(序号)特点:L1-2会自动下…