【高并发网络通信架构】2.引入多线程实现多客户端连接的tcp服务端

news2024/9/20 8:58:32

目录

一,往期文章

二,代码实现


一,往期文章

【高并发网络通信架构】1.Linux下实现单客户连接的tcp服务端

二,代码实现

关键代码

  • 因为accept是阻塞等待客户端连接,当客户端连接成功后才会执行accept后面的代码,所以为实现多个客户端连接,第一步是将accept放在master循环里。
  • recv是阻塞型函数,如果不将recv的相关代码放到线程里去,会导致客户端无法与服务端通信。

完整代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <pthread.h>

#define BUFFER_LENGTH   1024

void* threadCommunication(void *arg)
{
    int cfd = *(int*)arg;   //客户端文件描述符
    while(1)    //一直循环是确保一直和服务端通信,并且recv是阻塞函数
    {
        char data[BUFFER_LENGTH] = {0};
        int recLen = recv(cfd,data,BUFFER_LENGTH,0);
        if(recLen < 0){
            printf("recv error code: %d codeInfo: %s\n",errno,strerror(errno));
            return NULL;
        }else if(recLen == 0){
            //客户端断开连接
            printf("client fd %d disconnect\n",cfd);
            close(cfd);
            pthread_exit(NULL);
            break;
        }else{
            printf("recv fd %d data: %s\n",cfd,data);
            send(cfd,data,recLen,0);    //将接收到的数据重新发给客户端
        }
    }
    return NULL;
}

int init_server(int port){
    //获取服务端fd,通常为3,前面0,1,2用于指定输入,输出,错误值
    int sfd = socket(AF_INET,SOCK_STREAM,0);

    if(-1 == sfd){
        printf("socket error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    struct sockaddr_in servAddr;
    memset(&servAddr,0,sizeof(struct sockaddr_in));
    servAddr.sin_family = AF_INET;  //ipv4
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);   //0.0.0.0
    servAddr.sin_port = htons(port);
    
    //绑定IP和端口号
    if(-1 == bind(sfd,(struct sockaddr*)&servAddr,sizeof(struct sockaddr_in)))
    {
        printf("bind error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    //监听该套接字上的连接
    if(-1 == listen(sfd,10))
    {
        printf("listen error code: %d codeInfo: %s\n",errno,strerror(errno));
        return -1;
    }

    return sfd;
}

int main(int argc,char *argv[]){

    if(argc < 2)return -1;

    int port = atoi(argv[1]);
    int sfd = init_server(port);
    printf("server fd: %d\n",sfd);


    struct sockaddr_in servAddr;
    socklen_t len = sizeof(struct sockaddr_in);

    while (1)//每个服务器至少都有一个主循环
    {
        int cfd = accept(sfd,(struct sockaddr*)&servAddr,&len);

        pthread_t tid;
        int flag = pthread_create(&tid,NULL,threadCommunication,(void*)&cfd);
        if(0 == flag)
        {
            printf("client fd: %d ,thread ID: %ld start\n",cfd,tid);
        }
    }
    
    return 0;
}

运行效果

问题思考

  • 这种实现方式对于几十几百个客户端并发连接可能没问题,但对于成千上万的客户端进行高并发连接,仍采用这种方式来处理显然是不现实的?下一章介绍。。。

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

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

相关文章

简介Maven结构与配置方法

一、Maven是什么 Maven是apache旗下的一个开源项目&#xff0c;是一款用于管理和构建java项目的工具。 它有什么用呢&#xff1f; 比如我以前要IOUtils这个包&#xff0c;那要到网站下去下载下来&#xff0c;再导入。 当jar包多的时候&#xff0c;一个一个导出&#xff0c;…

开源Cillium项目为容器提供强大的网络功能

试验性的开源Cillium项目使用Linux内核的一项现有特性&#xff0c;为容器提供高速、强大的网络功能。一项名为Cilium的开源项目试图基于Linux内核中所用的技术&#xff0c;为容器提供一种新的网络方法。 试验性的开源Cillium项目使用Linux内核的一项现有特性&#xff0c;为容器…

ARM中断实验

#ifndef __KEY_H__ #define __KEY_H__#include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_exti.h" #include "stm32mp1xx_gic.h"//对RCC/GPIO/EXTI章节的初始化 void hal_key1_exti_init();//对GIC的初始…

算法笔记(Java)——链表篇

链表类问题通常比较简单&#xff0c;面试中应该不会出现这么简单的题型&#xff0c;需要注意的地方只有两个&#xff1a; 使用虚拟头节点增加便捷性判断链表是否有环 使用虚拟头节点 力扣题目链接&#xff1a; 203. 移除链表元素 这道题目比较简单&#xff0c;但是使用虚拟…

使用pyhton将文件夹内多个excel表格合并成总表

前言&#xff1a; 本文讲述使用python将需要处理的文件夹内多个excel文件内容进行合并&#xff0c;并输出为xlsx格式的总表。就比如一个文件夹里又有许多子文件夹&#xff0c;这些子文件夹里分布有excel文件&#xff0c;这里的python文件就能将这个文件夹内的所有excel文件进行…

【SpringMVC】| SpringMVC执行流程(含源码分析)

目录 SpringMVC执行流程 1. SpringMVC常用组件 2. DispatcherServlet初始化过程&#xff08;源码分析&#xff09; 3. DispatcherServlet调用组件处理请求 4. SpringMVC的完整执行流程 图书推荐&#xff1a;Spring Cloud Alibaba核心技术与实战案例 SpringMVC执行流程 1…

2.3.cuda驱动API-上下文管理设置及其作用

目录 前言1. CUcontext总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记 本次课程学习精简 CUDA 教程-Driver API 上下文管理设置及其作用 课…

css 中的几种颜色格式

css 中的几种颜色格式 css有一系列不同的颜色格式: 十六进制代码、RGB()、HSL()、lch()等等。 我们在使用的时候可能并不太注重这些。但是它们之前存在非常重要区别。本文会介绍不同的颜色格式及区别。 命名颜色 这并不是一种真正的颜色格式&#xff0c;但是对于初学者还是…

kube-proxy代理模式详解

kube-proxy代理模式详解 kube-proxy当前支持以下几种代理模式&#xff1a; 1、userspace&#xff1a;最早的负载均衡方案&#xff0c;它在用户空间监听一个端口&#xff0c;所有服务通过iptables转发到这个端口&#xff0c;然后在其内部负载均衡到实际的Pod。该方式最主要的问…

如何让大型语言模型(LLMs)遵守道德原则?

我们知道像ChatGPT那样的大型语言模型提供了内容审查机制&#xff0c;我们从openai的官方文档中可以看到open提供了Moderation的内容审查机制,主要包含以下11个方面&#xff1a; 从官方文档上看这11方面的审核机制似乎只停留在严格的法律层面的审查&#xff0c;但是对于那些没…

Java web开发--springboot

Java web开发--springboot Java有很多web框架 但是有的框架不是很好用:比如Java Servlets(个人感觉)不好调试,WEB-INF文件关联来关联去很烦躁,启动后 crtlc还关闭不了(我一般习惯用ctrlc命令来关闭服务).导致后面我调试springboot时一直报错,原来是Java Servlets的服务没关(我习…

Handshake failed due to invalid Upgrade header: null 解决方案以及连接60s,信息不交互,连接断开

Handshake failed due to invalid Upgrade header: null 解决方案以及连接60s&#xff0c;信息不交互&#xff0c;连接断开 1. 问题背景&#xff1a;因为后端用了nginx代理&#xff0c;所以websocket连接的过程中报错&#xff1a;Handshake failed due to invalid Upgrade hea…

[MySQL]数据类型(图文详解)

[MySQL]数据类型 文章目录 [MySQL]数据类型1. 数据类型分类2. 数值类型2.1 bit类型2.2 tinyint类型2.3 float类型2.4 decimal类型2.5 char类型2.6 varchar类型2.7 日期和时间类型2.8 enum和set类型 1. 数据类型分类 2. 数值类型 说明&#xff1a; 数值类型在定义时不加unsign…

【雕爷学编程】Arduino动手做(154)---AFMotor电机扩展板模块

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

备忘录模式的学习与使用

1、备忘录模式的学习 当您需要在不破坏封装性的前提下保存和恢复对象的状态时&#xff0c;备忘录模式是一种有用的设计模式。备忘录模式允许您将对象的状态保存到备忘录对象中&#xff0c;并在需要时从备忘录中恢复状态。这种模式分离了状态的保存和恢复逻辑&#xff0c;使得对…

stm32usart+中断接收定长数据

文章目录 前言一、cubemx的配置二、代码编写1.主函数在这里插入图片描述2. it.c 总结 前言 中断接收固定的数据值。 一、cubemx的配置 开启USART1 打开NVIC中断 二、代码编写 1.主函数 #define RxBuf_SIZE_1 50 //USART1接收缓冲区大小 #define MainBuf_SIZE_1 50 //USAR…

实现会议管理功能

目录 生成原始会议数据 一、数据结构 二、添加测试数据 查询会议列表分页数据&#xff08;后端&#xff09; 一、业务分析 二、编写持久层代码 三、编辑业务层代码 四、编写Web层代码 查询成员列表&#xff08;后端&#xff09; 一、编写持久层代码 二、编写业务层…

Mybatis-plus——查询条件设置+字段映射和表名映射

查询条件设置 等匹配查询 假如要进行登录查询的话&#xff0c;需要用到如下的等匹配&#xff0c;在实际的登录中应该做md5加密&#xff0c;从查询条件取出密码。 //条件查询LambdaQueryWrapper<mpdb> lqwnew LambdaQueryWrapper<mpdb>();//模拟登陆查询等匹配lqw…

SELF-ATTENTION DOES NOT NEED O(n2) MEMORY

背景 主要是要解决self-attention空间复杂度的问题&#xff0c;因为对于gpu计算来说&#xff0c;内存空间非常宝贵&#xff0c;序列长度较长的时候会出现oom问题。 用线性时间解决self-attention问题 解决数据稳定问题 因为由于进行求和计算&#xff0c;容易导致浮点数超过最…

栈区和堆区以及注意事项

>>栈区 #include<stdio.h> #include<string.h> #include<stdlib.h>int* func() {int a 10;//栈上创建的变量return &a; }void test01() {int* p func();//结果早已不重要&#xff0c;因为上面的a早已被释放&#xff0c;再去操作这块内存属于//非…