LINUX 入门 8

news2024/12/23 13:41:21

LINUX 入门 8

day10 20240507 耗时:90min 有点到倦怠期了

课程链接地址

第8章 TCP服务器

1 TCP服务器的介绍

开始讲服务器端,之前是客户端DNS+https请求

  1. 基础:网络编程
  2. 并发服务器:多客户端
    1. 一请求,一线程 veryold
    2. IO多路复用,epoll/select上一章讲过了
  3. TCP server百万级连接

借助netassist.exe

2 TCP并发网络网络编程 一请求一线程

tcp server类似酒店迎宾领过去,监听listen

server有对应客户端的连接有socket 连接类似服务员点菜

没懂好多用法

  1. void *client_routine(void *arg){
        int clientfd = *(int *) arg;
    } 
    

    这是一个使用多线程处理客户端请求的例子。在这个例子中,每个客户端连接都会创建一个新的线程,并且通过 client_routine 函数进行处理。

    下面是对提供的代码片段的解释:

    • void *client_routine(void *arg) 是一个线程函数,用于处理单个客户端连接。
    • int clientfd = *(int *) arg; 将传入参数 arg 解引用为整数类型,并将其赋值给 clientfd 变量。假设传入参数是一个指向整数类型的指针,即客户端套接字描述符。 *(int *) arg;它首先将 arg 强制转换为指向整数的指针,然后使用解引用操作符 * 获取该指针所指向的值。

    你可以在该函数中编写适当的代码来处理客户端请求,例如读取和发送数据等操作。请注意,在每个线程内部需要负责释放相关资源并确保线程安全性。

步骤:

gcc -o tcp_server tcp_server.c -lpthread
./tcp_server 8888

服务器就起来了

打开netassist 改远程地址: 192.168.243.128:8888

在这里插入图片描述

有bug连上了,但是点发送以后收不到!!!

或者是bind error, 没调出来,可能那里打错了,老师的是可以的

  1. 起多个客户端send,如何取区分

    sockfd无法解决,需要应用协议发的内容不同<fromid: xxxx>

  2. 缺点:不适合超多client,内存不够; 用epoll改

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <pthread.h>

#include <errno.h>
#include <fcntl.h>

#include <sys/epoll.h>
#include <unistd.h> //close要


#define BUFFER_LENGTH 1024

// 法一 一请求一线程
void *client_routine(void *arg){
    int clientfd = *(int *) arg;
    while(1){
        char buffer[BUFFER_LENGTH] = {0}; 
        // 用于从客户端套接字中接收数据并将其存储到缓冲区中。clientfd:表示要接收数据的套接字文件描述符。buffer:表示接收数据的缓冲区,也就是存放接收到的数据的位置。BUFFER_LENGTH:表示期望接收的最大字节数,即缓冲区的大小。0:表示额外选项,通常设置为 0。
        int len = recv(clientfd, buffer, BUFFER_LENGTH, 0);
        if(len < 0){
            // 没数据,如果阻塞,就是一直等,返回-1
            // 在非阻塞 I/O 模式下,当没有可用数据时,recv() 函数可能返回 -1 并设置 errno 为 EAGAIN 或 EWOULDBLOCK。这表示当前没有数据可供接收,并且稍后可能会有更多数据可用。因此,这段代码的作用是检测 errno 是否等于 EAGAIN 或 EWOULDBLOCK,以判断是否需要继续等待更多数据的到达。
            if(errno == EAGAIN ||errno == EWOULDBLOCK){
                close(clientfd);
                break;
            }else if(len == 0){ //disconnect
                close(clientfd);
                break;
            }else{
                printf("recv: %s, %d byte(s)\n",buffer, len);
            }
        }
    }
} 

// 1 socket创建
int main(int argc, char*argv[]){
    if(argc<2) {
        printf("param error\n");
        return -1;
    }

    int port = atoi(argv[1]);

    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //聘请一个迎宾的listen

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family  = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY; //任意地址不确定

    // 0成功 1失败
    // 函数bind()将套接字与特定的IP地址和端口号进行绑定,以便后续接收来自该地址的连接请求。
    // 而listen()则表示开始监听连接请求,并指定最大允许等待连接队列的长度为5。这意味着服务器可以同时处理5个未处理的连接请求,超过这个数量的请求将被拒绝或排队等待处理。
    if(bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0){
        perror("bind error");
        return -2;
    }
    if(listen(sockfd, 5) < 0){
        perror("listen error");
        return -3;
    } 

    // 2迎宾sockfd 一直等着 为客户client介绍服务员socket
    while(1){
        struct sockaddr_in client_addr;
        memset(&client_addr, 0, sizeof(struct sockaddr_in));
        
        socklen_t client_len = sizeof(client_addr);
        
        // 使用accept函数接受来自服务器监听套接字 sockfd 的客户端连接请求,并将客户端的地址信息存储在名为 client_addr 的结构体中。
        int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len); 

        // 法一 一请求一线程
        // 请求来了创建线程
        pthread_t thread_id;
        pthread_create(&thread_id, NULL, client_routine, &clientfd);
    }



}

3 TCP并发网络编程io多路复用epoll 水平触发与边沿触发

没敲,就看了一下

  1. what is epoll

    超多clients 对server发request

    检测到哪个client发了数据

    1. epoll_create
    2. epoll_ctl control管理 增删改
    3. epoll_wait() 多长时间去一次
#if 0

	while (1) {

		struct sockaddr_in client_addr;
		memset(&client_addr, 0, sizeof(struct sockaddr_in));
		socklen_t client_len = sizeof(client_addr);

		int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
		
		pthread_t thread_id;
		pthread_create(&thread_id, NULL, client_routine, &clientfd);

	}
	
#else

	int epfd = epoll_create(1);  
	struct epoll_event events[EPOLL_SIZE] = {0};

	struct epoll_event ev;
	ev.events = EPOLLIN; 
	ev.data.fd = sockfd;
	epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);

	
	while (1) {

		int nready = epoll_wait(epfd, events, EPOLL_SIZE, 5); // -1, 0, 5
		if (nready == -1) continue;

		int i = 0;
		for (i = 0;i < nready;i ++) {

			if (events[i].data.fd == sockfd) { // listen 

				struct sockaddr_in client_addr;
				memset(&client_addr, 0, sizeof(struct sockaddr_in));
				socklen_t client_len = sizeof(client_addr);

				int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);

				ev.events = EPOLLIN | EPOLLET; 
				ev.data.fd = clientfd;
				epoll_ctl(epfd, EPOLL_CTL_ADD, clientfd, &ev);

			} else {

				int clientfd = events[i].data.fd;
				
				char buffer[BUFFER_LENGTH] = {0};
				int len = recv(clientfd, buffer, BUFFER_LENGTH, 0);
				if (len < 0) {
					close(clientfd);

					ev.events = EPOLLIN; 
					ev.data.fd = clientfd;
					epoll_ctl(epfd, EPOLL_CTL_DEL, clientfd, &ev);
					
				} else if (len == 0) { // disconnect
					close(clientfd);

					ev.events = EPOLLIN; 
					ev.data.fd = clientfd;
					epoll_ctl(epfd, EPOLL_CTL_DEL, clientfd, &ev);
					
				} else {
					printf("Recv: %s, %d byte(s)\n", buffer, len);
				}
				
				
			}

		}

	}
	

#endif
	

一边听,敲,记笔记云里雾里的

  1. 关于io有无数据?如何检测 epoll_wait
    1. 有1 无0
    2. 一种是水平触发EPOLLIN:有没有;一种是边沿触发EPOLLET:检测从无变有

**面试重点:**epoll两种触发,reactor,协程,epoll 在sockfd set集合里

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

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

相关文章

物联网SCI期刊,潜力新刊,审稿速度快,收稿范围广泛!

一、期刊名称 Internet of Things 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;物联网 影响因子&#xff1a;5.9 中科院分区&#xff1a;3区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支付$2310 三、期刊征稿范围 I…

终端安全管理防护软件排行榜2024(四大终端监控软件推荐)

你的企业存在这些问题吗&#xff1f; 数字化转型的深入和远程办公模式的普及&#xff0c;企业对终端安全管理的需求日益凸显。 确保终端设备的安全性不仅关乎数据保护、业务连续性&#xff0c;更直接影响企业的声誉与合规性。 2024年终端安全防护软件排行榜&#xff0c;有谁荣…

【驱动】SPI

1、简介 SPI(Serial Peripheral interface)串行外设接口。 特点: 高速:最大几十M,比如,AD9361的SPI总线速度可以达到40MHz以上全双工:主机在MOSI线上发送一位数据,从机读取它,而从机在MISO线上发送一位数据,主机读取它一主多从:主机产生时钟信号,通过片选引脚选择…

2024第十六届“中国电机工程学会杯”数学建模A题B题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

vue3+TS或JS, 实现粒子特效 @tsparticles/vue3

在跟着B站视频BV11s4y1a71T学习时&#xff0c;使用到了粒子效果&#xff0c;但是以下这种情况只适用于项目是基于typescript的写法&#xff0c;否则无法实现。 粒子效果 VUE3TStsparticles/vue31、安装2、main.ts 引入3、App.vue4、效果 VUE3JS非最新版1、安装低版本的vue3-pa…

流量分析(一)

数据库类流量分析 MySQL流量 常规操作&#xff0c;查找flag ctfhub{} 注意要选择字符集 Redis流量 查找ctfhub结果没找到 尝试把其变成十六进制继续进行查找 看到了前半段flag 接着往下看 找到了后半段的flag MongoDB流量 还是一样查找ctfhub 字符串没找到 转成十六进制也没…

Leetcode—295. 数据流的中位数【困难】

2024每日刷题&#xff08;132&#xff09; Leetcode—295. 数据流的中位数 实现代码 class MedianFinder { public:MedianFinder() {}void addNum(int num) {if(maxHeap.empty() || num < maxHeap.top()) {maxHeap.push(num);} else {minHeap.push(num);}if(maxHeap.size(…

算法学习笔记(2)-前缀和

##前缀和 指的是某序列的前n项和&#xff0c;在数学上我们可以理解称为数列的前n项和。前缀和是一种预处理&#xff0c;用于降低查询的时间复杂度。 ##一维前缀和 有一个一维数组x和该数组的前缀和数组y&#xff0c;则x和y具有以下关系&#xff1a; #python代码示例 #关系&am…

WorkPlus im(即时通讯)集成平台助力政企数字化转型升级

随着互联网技术的不断发展&#xff0c;企业内部通讯软件已经成为企业日常运营中不可或缺的一部分。企业IM&#xff08;即时通讯&#xff09;和移动门户作为企业内部通讯软件的关键组成部分&#xff0c;为企业提供更加高效、便捷的通讯方式&#xff0c;提高了企业的运营效率。 针…

ETLCloud中如何执行Java Bean脚本

ETLCloud中如何执行Java Bean脚本 在ETLCloud这一强大的数据集成和转换平台中&#xff0c;执行Java Bean脚本的能力为其增添了更多的灵活性和扩展性。Java Bean脚本不仅仅是一段简单的代码&#xff0c;而是一种强大的工具&#xff0c;可以帮助用户定制和优化数据处理的每一个环…

笨方法自学python(六)-字符串和文本

上一节中出现了\n&#xff0c;这个作用是换行。\后面带不同字符有不同的作用&#xff0c;我们先简单了解几个&#xff0c; 使用反斜杠 \ (back-slash) 可以将难打印出来的字符放到字符串。针对不同的符号有很多这样的所谓“转义序列(escape sequences)”&#xff0c;我们来练习…

IDEA 常见设置问题

OutOfMemoryError IDEA 第一次运行项目时&#xff0c;会报错误 - java.lang.OutOfMemoryError: Java heap space / insufficient memory&#xff0c;解决办法是&#xff1a; 将图示部分由默认的 700 改为 2048。 import * 工程lint检查时不允许使用import *&#xff0c;IDE…

时间范围交集查询

业务场景&#xff1a; 数据库中时开始时间与结束时间&#xff0c;筛选数据条件将这两个字段&#xff08;开始时间、结束时间&#xff09;糅合成一个字段&#xff0c;并且是范围筛选。 数据库字段&#xff1a; 筛选条件&#xff1a; 数据分析 全部包含&#xff08;子集&#…

短视频收益分成一览表​​​​​​​​​​​​​​​​,视频号怎么做有收益的

今日为大家揭秘一个热门视频号的操作技巧。很多人都已经操作这类账号&#xff0c;并从中获益。视频号目前是市场上非常热门的平台之一&#xff0c;流量之大令人惊叹&#xff0c;先不提那些私域营销的巨大优势&#xff0c;仅从创作分成计划角度来看&#xff0c;已有许多人每天能…

【前端】桌面版docker并部署前端项目

环境 win10专业版 2004 , 需科学 官网下载安装包并安装4.29.0版本 终端输入 wsl --installdocker桌面版和模拟器只能选一个&#xff0c;不然一直转圈圈 镜像配置加速&#xff0c;在settings—>docker engine下 {"builder": {"gc": {"defaultKee…

docker私有仓库registry

简介 Docker私有仓库的Registry是一个服务&#xff0c;主要用于存储、管理和分发Docker镜像。具体来说&#xff0c;Registry的功能包括&#xff1a; 存储镜像&#xff1a;Registry提供一个集中的地方来存储Docker镜像&#xff0c;包括镜像的层次结构和元数据。 版本控制&…

揭秘LLMOps,高效开发大型语言模型

大家好&#xff0c;随着人工智能&#xff08;AI&#xff09;的蓬勃发展&#xff0c;一个新兴领域语言模型运维&#xff08;LLMOps&#xff09;正逐渐成为关注的焦点。LLMOps专注于对大型语言模型&#xff08;LLMs&#xff09;&#xff0c;例如OpenAI的GPT系列&#xff0c;进行全…

无需设置环境变量,Linux下最正确的Java离线安装方式

背景 公司研发网络是离线环境&#xff0c;需要安装Java环境&#xff0c;网上教程大多是在线安装或者通过设置环境变量安装&#xff0c;设置环境变量的方式是最常见的&#xff0c;但确隐藏了很多坑&#xff0c;例如环境变量有时候会不生效&#xff0c;如果你的程序通过systemd启…

ok_Keil实用小技巧 | Keil定制Hex文件名实现的方法

Keil实用小技巧 | Keil定制Hex文件名实现的方法 echo off REM 可执行文件&#xff08;Hex&#xff09;文件名 set HEX_NAMEDemo REM 可执行文件&#xff08;Hex&#xff09;文件路径 set HEX_PATH.\Objects REM 定制Hex输出路径 set OUTPUT_PATH.\Output REM 软件版本文件…

应用案例 | 商业电气承包商借助Softing NetXpert XG2节省网络验证时间

一家提供全方位服务的电气承包商通过使用Softing NetXpert XG2顺利完成了此次工作任务——简化了故障排查的同时&#xff0c;还在很大程度上减少了不必要的售后回访。 对已经安装好的光纤或铜缆以太网网络进行认证测试可能会面临不同的挑战&#xff0c;这具体取决于网络的规模、…