tcp连接的select

2023-05-16

tcp的socket不同于udp

tcp:建立socket的fd;bind;listen;accept;send or recv。另一端connect(客户端)

udp:                        ;bind;                        ;send or recv。另一端直接recv or send

select步骤:

1、fd_set(1024位的bitmap,包括清空【FD_ZERO】,把我的TCPsocket句柄放入这个bitmap【FD_SET】这是一个置位操作故不可重复利用,需清空某个位置后在使用【FD_CLR】会把bitmap相对应的socket置为0,最重要的轮询检查这个fd_set里哪些位置被监听【FD_ISSET】)

2、调用select(maxsock+1,fd_set,写,异常,timeout);//参数一是最大句柄数+1也就是是bitmap的长度,第二个参数标识读文件描述符,这个select只处理读句柄

3、轮询check每一个fd在fd_set中的状态,1表示监听,0表示不监听,对于监听的端口使用socket的recv()函数接收数据来读,相反,如果是写句柄则调用send()函数发送数据去写如另一个进程。

4、每次轮询完已有的fd_set,检查是否有新的fd连接进来【FD_ISSET】如果有则bitmap的大小 maxsock++

缺点:

bitmap只有1024位--------->>>>>>poll采用链表把所有的结构体连接起来,对pollfd。revents置位

fd_set不可重用,每次都要创建一个新的---------->>>>>poll

用户态和内核态的切换要开销--------->>>>>epoll不需要切换

再次遍历bitmap的时间复杂度O(n)--------->>>>>epoll改进,epoll_wait()每次把监听端口的epfd排序,放在前面并返回个数,每次遍历返回个数就可以获取全部监听socket

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 1234    // the port users will be connecting to
#define BACKLOG 5     // how many pending connections queue will hold
#define BUF_SIZE 1024
int fd_A[BACKLOG];    // accepted connection fd
int conn_amount;      // current connection amount
void showclient()
{
    int i;
    printf("client amount: %d/n", conn_amount);
    for (i = 0; i < BACKLOG; i++) {
        printf("[%d]:%d  ", i, fd_A[i]);
    }
    printf("/n/n");
}
int main(void)
{
    int sock_fd, new_fd;             // listen on sock_fd, new connection on new_fd
    struct sockaddr_in server_addr;  // server address information
    struct sockaddr_in client_addr;  // connector's address information
    socklen_t sin_size;
    int yes = 1;
    char buf[BUF_SIZE];
    int ret;
    int i;
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }
    if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    server_addr.sin_family = AF_INET;         // host byte order
    server_addr.sin_port = htons(MYPORT);     // short, network byte order
    server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
    memset(server_addr.sin_zero, '/0', sizeof(server_addr.sin_zero));
    if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        exit(1);
    }
    if (listen(sock_fd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }
    printf("listen port %d/n", MYPORT);
    fd_set fdsr;
    int maxsock;
    struct timeval tv;
    conn_amount = 0;
    sin_size = sizeof(client_addr);
    maxsock = sock_fd;
    while (1)
    {
        // initialize file descriptor set
        FD_ZERO(&fdsr);
        FD_SET(sock_fd, &fdsr);  // add fd
        // timeout setting
        tv.tv_sec = 30;
        tv.tv_usec = 0;
        // add active connection to fd set
        for (i = 0; i < BACKLOG; i++) {
            if (fd_A[i] != 0) {
                FD_SET(fd_A[i], &fdsr);
            }
        }
        ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);
        if (ret < 0) {          // error
            perror("select");
            break;
        } else if (ret == 0) {  // time out
            printf("timeout/n");
            continue;
        }
        // check every fd in the set
        for (i = 0; i < conn_amount; i++)
        {
            if (FD_ISSET(fd_A[i], &fdsr)) // check which fd is ready
            {
                ret = recv(fd_A[i], buf, sizeof(buf), 0);
                if (ret <= 0)
                {        // client close
                    printf("ret : %d and client[%d] close/n", ret, i);
                    close(fd_A[i]);
                    FD_CLR(fd_A[i], &fdsr);  // delete fd
                    fd_A[i] = 0;
                    conn_amount--;
                }
                else
                {        // receive data
                    if (ret < BUF_SIZE)
                        memset(&buf[ret], '/0', 1); // add NULL('/0')
                    printf("client[%d] send:%s/n", i, buf);
                }
            }
        }
        // check whether a new connection comes
        if (FD_ISSET(sock_fd, &fdsr))  // accept new connection
        {
            new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
            if (new_fd <= 0)
            {
                perror("accept");
                continue;
            }
            // add to fd queue
            if (conn_amount < BACKLOG)
            {
                fd_A[conn_amount++] = new_fd;
                printf("new connection client[%d] %s:%d/n", conn_amount,
                        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                if (new_fd > maxsock)  // update the maxsock fd for select function
                    maxsock = new_fd;
            }
            else
            {
                printf("max connections arrive, exit/n");
                send(new_fd, "bye", 4, 0);
                close(new_fd);
                break;   
            }
        }
        showclient();
    }
    // close other connections
    for (i = 0; i < BACKLOG; i++)
    {
        if (fd_A[i] != 0)
        {
            close(fd_A[i]);
        }
    }
    exit(0);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

tcp连接的select 的相关文章

  • 通过 TCP 客户端套接字接收数据时出现问题

    我正在尝试用 C 语言编写一个 TCP 客户端程序 客户端将在其中启动 连接到服务器 然后它会发送一些信息 然后监听它收到的信息并做出相应的反应 我遇到麻烦的部分是持续聆听 这是我所拥有的 while 1 numbytes recv soc
  • 查找网络中的所有IP地址

    我正在尝试用 C 来做这个 我需要找到我的网络中所有活动的 IP 地址并将它们显示在列表中 我可以 ping 网络中所有可用的 1 255 IP 地址 但我想让这个过程更快 此代码在大约 1 秒内扫描我的网络 255 个 D 级段 我在 V
  • 从两个表中选择最大值、最小值

    我有两张桌子 不同之处在于 归档是一个表 另一个保存当前记录 这些是记录公司销售额的表格 在这两个字段中 我们都有其他字段 id 名称 销售价格 我需要从两个表中选择给定名称的最高价格和最低价格 我尝试处理查询 select name ma
  • Android TCP 连接最佳实践

    我正在开发一个需要 TCP 连接到 TCP 服务器的 Android 应用程序 用 Node js 编写 我的 Android TCP 客户端正在工作 可以来回发送消息 我的具体问题是 在 Android 中处理与服务器的 TCP 连接的最
  • 是否可以通过 TCP 连接到正在侦听 3G 网络端口的 iPhone?

    我正在开发一个严重依赖 P2P 的应用程序 但我目前没有任何 SIM 卡可供实验 因此我正在 wifi 网络上进行测试 我想知道 3G 网络上的 iPhone 是否可以连接以及是否需要穿越 NAT 设备 您位于提供商的路由器后面 您的 IP
  • 如何根据多个字段选择不同的行

    我有一个表 其中包含 MSSQL 数据库中一系列事件的数据 ID Name Date Location Owner 1 Seminar Name 1 2013 08 08 A Location Name
  • ORACLE Select Distinct 返回许多列,其中

    我有一个看起来像这样的表 NAME Col1 Col2 Col3 Tim 1 2 3 Tim 1 1 2 Tim 2 1 2 Dan 1 2 3 Dan 2 2 1 Dan 2 1 3 我试图创建一个 SELECT 命令 结果如下 NAME
  • MySQL 返回用户排名最高的事件

    我目前使用以下查询来获取每个用户的详细信息 SELECT u sums total votes sums no of events FROM user u LEFT JOIN SELECT us user uid count ev even
  • 熊猫选择倒数第二列,这也不是 nan

    我已尽可能多地清理数据并在 Pandas 数据框中读取它们 所以问题是不同的文件有不同的列数 但它总是倒数第二个非纳米列是我想要的 那么有什么办法可以把它们挑出来吗 这是数据的示例 f g h l 0 39994 29 568 29 569
  • Go TCP 读取是非阻塞的

    我正在尝试用 Go 创建服务器和客户端 我已经成功地与服务器和客户端进行通信 但我遇到的问题是golang中的TCP读取是非阻塞的 我想知道 golang 中的读取是否有可能像 C 中的读取一样阻塞 谢谢 EDIT 这是服务器的源代码 fu
  • 为什么我们可以将 sockaddr 转换为 sockaddr_in

    我明白为什么强制转换很有用sockaddr to sockaddr in 但我不明白这怎么可能 据我所知 它们的大小相同sockaddr in添加了sin zero使其大小相同 我想知道编译器如何知道从哪里获取信息sockaddr in如果
  • MySQL 错误:#1142 - SELECT 命令被拒绝给用户

    我在一台服务器上的某个查询时遇到问题 在我测试过的所有其他地方 它工作得很好 但在我想使用它的服务器上 它不起作用 这是关于以下 SQL SELECT facturen id AS fid projecten id AS pid titel
  • 为什么这个简单的 MySQL 查询不返回该行?

    我在表中有一行users与用户名test 但由于某种原因 此查询返回空结果集 SELECT id FROM users WHERE username test AND id null 但是 如果我删除 id null段 查询返回结果id 1
  • jQuery - 选择同一级别的div

    我想在单击按钮时选择一个特定的div 唯一的问题是 它必须是buttonClicked的父div的div 示例 div class container div class box h2 Langtidsparkering h2 div cl
  • C# Socket.receive连续接收0字节且循环中不阻塞

    我正在尝试用 C 编写一个最简单的多线程 TCP 服务器 它接收来自多个客户端的数据 每次连接新客户端时 都会建立套接字连接 并将套接字作为参数传递给新类函数 之后运行 while 循环并接收数据 直到客户端连接为止 这里的问题是 sock
  • 当Where子句中的术语不在数据库中时,如何从MySQL数据库返回0?

    如果 WHERE 子句中的邻域不存在 如何让 mysql 数据库返回 0 因此 在下面的示例中 旧城区不在数据库中 我希望数据库返回 0 个事件而不是空结果 SELECT incidents neighborhoods FROM myTab
  • Linq:Select 和Where 之间有什么区别

    The Select and WhereLinq 中提供了方法 对于这两种方法 每个开发人员都应该了解什么 例如 何时使用其中一种而不是另一种 使用一种相对于另一种的优势等 Where 查找匹配的项目并仅返回匹配的项目 过滤 gt IEnu
  • 访问 AWS 上的 Tensorboard

    我正在尝试访问 AWS 上的 Tensorboard 这是我的设置 张量板 tensorboard host 0 0 0 0 logdir train 在端口 6006 上启动 TensorBoard b 39 您可以导航到http 172
  • 无法分配请求的地址 - 可能的原因?

    我有一个由主服务器和分布式从服务器组成的程序 从属服务器向服务器发送状态更新 如果服务器在固定时间内没有收到特定从属服务器的消息 则会将该从属服务器标记为关闭 这种情况一直在发生 通过检查日志 我发现从站只能向服务器发送一个状态更新 然后永
  • 为什么 UDP 服务器中只有一个套接字?

    我正在准备考试 发现了这个问题 典型的 UDP 服务器可以使用单个套接字来实现 解释一下为什么 对于 TCP 驱动的服务器 我发现创建了两个套接字 一个用于所有客户端访问服务器 另一个用于每个客户端的特定 套接字 用于服务器和客户端之间的进

随机推荐

  • 嵌入式硬件-读懂原理图

    学习硬件的第一节课 学习读懂原理图 读懂原理图对嵌入式软件工程师和程序员尤为重要 在深入细节之前请注意 对所有的嵌入式设计人员来说 能懂得硬件工程师创建和使用的来描述其硬件设计的原理图和符号是非常重要的 无论硬件设计得多么复杂 不管有多少设
  • 校招行测笔试-图形推理

    校招行测笔试 图形推理 面对校招笔试的行政能力测试 xff08 简称 行测 xff09 环节 xff0c 刚开始接触有些束手无策 摸不到头脑 xff0c 其实是有技可循的 xff0c 本文就帮助大家总结一下行测的相关技巧 如果对你有所帮助
  • 统一建模语言UML详解附思维导图

    UML图 概述 构成 事物 Things xff1a UML模型中最基本的构成元素 xff0c 是具有代表性的成分的抽象 构件事物 xff1a UML模型的静态部分 xff0c 描述概念或物理元素 类 xff1a 具有相同属性相同操作 相同
  • 比特率与波特率

    比特率 xff1a 单位 Bps bit per second xff0c 即每秒传输的 bit 数 波特率 xff1a 单位 Baud xff0c 即每秒传输的 码元 数 这里涉及到码元 码元 xff1a 持续一段固定时间的通信信道有效状
  • 嵌入式相关开源项目、库、资料------持续更新中

    学习初期最难找的就是找学习资料了 xff0c 本贴精心汇总了一些嵌入式相关资源 xff0c 包括但不限于编程语言 单片机 开源项目 物联网 操作系统 Linux 计算机等资源 xff0c 并且在不断地更新中 xff0c 致力于打造全网最全的
  • 嵌入式系统QNX概述-微内核架构进程管理安全性

    一 微内核架构 QNX操作系统由微内核以及一组协作的系统服务进程组成服务进程与操作系统内核是相互隔离开的 当服务进程出问题时并不会影响内核微内核提供软件总线供各个软件模块进行通信和协作内核只提供最小化的基础 公共服务高度模块化设计带来良好的
  • 三万字长文总结C语言规范

    1 头文件 若包含了头文件aa h xff0c 则就引入了新的依赖 xff1a 一旦aa h被修改 xff0c 任何直接和间接包含aa h代码都会被重新编译 如果aa h又包含了其他头文件如bb h xff0c 那么bb h的任何改变都将导
  • 操作系统概述

    Overview Q1 xff08 Why xff09 为什么要学操作系统 xff1f Q2 xff08 What xff09 xff1a 到底什么是操作系统 xff1f Q3 xff08 How xff09 xff1a 怎么学操作系统 x
  • 小白自学PIX飞控学习笔记

    小白自学PIX飞控学习笔记 xff08 二 xff09 接触飞控什么是MCU xff1f PIX飞控与MCU xff1f 无人机飞控的作用飞控内部如何实现其功能 xff1f 接触飞控 作为未入门 小白 一枚 xff0c 也只是简单地接触过C
  • Nestjs 返回req报错

    返回req存在循环引用 报错 ERROR ExceptionsHandler Converting circular structure to JSON gt starting at object with constructor Sock
  • 设计方法的选用

    六大原则 创建好了之后算法不常变的 xff0c 比如计算器的加减乘除逻辑 xff0c 就可以用简单工厂模式 要是像商场收银机对打折等促销的处理 xff0c 若用简单工厂模式也可以 xff0c 不过要在工厂内创建多个具体的打折方案 xff0c
  • XXX测试用例设计?XXX怎么测试?(行李箱、电梯、水杯、笔、椅子)

    首先要知道 xff0c 答案要从下面6个方向考虑 xff1a 功能测试 界面测试 易用性测试 兼容性测试 安全性测试 性能测试 其次 xff0c 在回答问题前要向面试官表明 xff1a 我不知道XXX的具体需求 xff0c 所以会以我认知的
  • 面试——测试基础理论

    测试先导性知识 测试是什么 xff1f 在规定的条件下对程序进行操作去发现错误 xff0c 然后对软件质量进行评估的一个过程 需要注意的是 xff0c 软件是由文档 数据以及程序组成的 xff0c 所以对软件测试应该包括 xff1a 软件形
  • 【ubuntu16.04 LTS】 ping www.baidu.com不通

    想更新一个软件包 xff0c 发现ubuntu不能正常更新 xff0c 结果ping www baidu com不通 xff0c 但是ping ip 可能 xff0c 所以认为是DNS没有配置 解决方法 xff1a 1 xff0c 既然能p
  • 小鼠试毒问题(二进制)

    1000桶酒 xff0c 其中1桶有毒 而一旦吃了 xff0c 毒性会在1周后发作 问最少需要多少只老鼠可在一周内找出毒酒 如题 分析思路 xff1a 要用尽可能少的老鼠完成相对大的任务量 xff0c 要想到把问题进行对数分解 从而不难想到
  • wsl,Ubuntu,关于解决E: Could not read response to hello message from hook [ ! -f /usr/bin/snap ] || /usr/

    大坑 出现问题 xff1a 今天安装mysql xff0c sudo apt span class token operator span get install mysql span class token operator span s
  • wsl,win10子系统Ubuntu,安装mysql过程及坑

    一 安装 sudo apt span class token operator span get install mysql span class token operator span server 二 启动服务 注意 xff1a 先停止
  • 外接显示器调亮度解决方案(最低亮度后还是很亮)

    出现的问题 xff1a 手动调显示屏调亮度的键 xff0c 发现调到最低亮度后还是很亮 解决方案 xff1a 使用显卡设置来调整 win10 xff1a 桌面右键 英特尔显卡设置 显示器 颜色设置 选择显示器 应用
  • Java-线程,多线程同步安全案例,多窗口卖票一共有 50张票 ,4个窗口出售,打印出票售出的顺序。

    一共有 50张票 xff0c 4个窗口出售 xff0c 打印出票售出的顺序 span class token keyword package span com span class token punctuation span proble
  • tcp连接的select

    tcp的socket不同于udp tcp xff1a 建立socket的fd xff1b bind xff1b listen xff1b accept xff1b send or recv 另一端connect xff08 客户端 xff0