libuv 应用

news2024/11/25 2:58:00

找到了一份示例代码.根据实际情况做了修改

#include <arpa/inet.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>

#define DEFAULT_PORT 4080
#define DEFAULT_BACKLOG 128

uv_loop_t *loop;
struct sockaddr_in addr;

typedef struct {
  uv_write_t req;
  uv_buf_t buf;
} write_req_t;

void free_write_req(uv_write_t *req) {
  // 释放的时候注意先将对象内部使用的缓存释放,然后再释放对象本身
  write_req_t *wr = (write_req_t *)req;
}

void echo_write(uv_write_t *req, int status) {
  if (status) {
    // 状态值status不为0表示发送数据失败。
    fprintf(stderr, "Write error %s\n", uv_strerror(status));
  }
  // 不管发送数据成功与否,都要执行下面的函数释放资源,以免内存泄露
  free_write_req(req);
}

struct network_client {
  bool alive;
  struct sockaddr_in addr;
  int32_t index;
  uv_tcp_t client;
  char buf[4096];
};

struct network {
  bool full;
  int32_t n_client;
  struct network_client client[255];
};

void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
  if (nread > 0) {
    struct network_client *net = client->data;
    nread = nread > 4096 ? 4096 : nread;
    net->alive = true;
    memcpy(net->buf, buf->base, nread);
  } else {
    if (nread != UV_EOF)
      fprintf(stderr, "Read error %s\n", uv_err_name(nread));
    uv_close((uv_handle_t *)client, NULL);
  }
}

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
  static char buffer[4096];
  bzero(buffer, sizeof(buffer));
  buf->base = buffer;
  buf->len = 4096;
}

void on_new_connection(uv_stream_t *server, int status) {
  if (status < 0) {
    fprintf(stderr, "New connection error %s\n", uv_strerror(status));
    return;
  }
  struct network *center = server->data;
  center->n_client++;
  if (center->n_client >= sizeof(center->client) / sizeof(center->client[0])) {
    center->n_client = 0;
  }
  int32_t *index = &center->n_client;
  center->client[*index].index = *index;
  center->client[*index].client.data = &center->client[*index];
  uv_tcp_init(server->loop, &center->client[*index].client);
  if (uv_accept(server, (uv_stream_t *)&center->client[*index].client) == 0) {
    int32_t len = sizeof(struct sockaddr);
    // TODO: get accept addr information
    uv_tcp_getpeername(&center->client[*index].client,
                       (struct sockaddr *)&center->client[*index].addr, &len);
    uv_read_start((uv_stream_t *)&center->client[*index].client,
                  server->alloc_cb, server->read_cb);
  } else {
    uv_close((uv_handle_t *)&center->client[*index].client, NULL);
  }
}

int32_t network_deal(struct network *center) {
  for (int32_t i = 0; i < 255; i++) {
    if (center->client[i].alive) {
      printf("index:%d %s: %s\n", i, inet_ntoa(center->client[i].addr.sin_addr),
             center->client[i].buf);
      center->client[i].alive = false;
      center->n_client--;
    }
  }
  return 0;
}

#include <stdlib.h>
#include <time.h>
#include <unistd.h>

void *run(void *args) {
  while (1) {
    while (((struct network *)args)->n_client == 0) {
      usleep(500);
    }
    network_deal(args);
  }
}

int main() {
  struct network net;
  loop = uv_default_loop();
  uv_tcp_t server;
  uv_tcp_init(loop, &server);
  uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
  uv_tcp_bind(&server, (const struct sockaddr *)&addr, 0);
  server.data = &net;
  server.loop = loop;
  server.alloc_cb = alloc_buffer;
  server.read_cb = echo_read;
  int r = uv_listen((uv_stream_t *)&server, DEFAULT_BACKLOG, on_new_connection);
  if (r) {
    fprintf(stderr, "Listen error %s\n", uv_strerror(r));
    return 1;
  }
  pthread_t tid;
  pthread_create(&tid, 0, run, &net);
  return uv_run(loop, UV_RUN_DEFAULT);
}

测试使用的脚本

#!/bin/bash
TEST_GAP=1
TEST_IP=127.0.0.1
TEST_PORT=7000
tcpLoop(){
    while `sleep ${TEST_GAP}` ; do
        echo $@ | socat - tcp-connect:${TEST_IP}:${TEST_PORT}
    done
}

for t in {1..10000} ; do
  tcpLoop test ${t} &
done

内存动态分配 更好些,大量测试有可能访问了,栈区,不可读可写的地方,容易发生 SEGMENTFAULT ,频繁,动态的堆区更合适
上面只是一个测试代码,不建议使用
举个例子,因为没有this 指针,我更喜欢用 contain_of 计算机构体的位置
堆上的内存没出过错,但是,我用静态的存储方式,寻找结构体就发生了 SEGMENTFAULT ,地址非法访问
libuv 的表现linux 的嵌入式设备上,应该很炸裂,用了2004 的交叉编译链,成功编译过去了,开心 … …

知乎 上关于 poll_wait 的源码解释

在这里插入图片描述

timer 过期,我真的日 … … 这就是面代码不能用的原因

再来一张,GDB 手术结果

在这里插入图片描述

调用栈, 和 变量的实时结果

娘的为什么

按照手册,就正常了 … …

在这里插入图片描述

更新计时器, 娘的

timer 正常更新 … …

找到了原因,开心,这个玩意不要乱用… … (不然计时器更新会出现异常)
在这里插入图片描述

调用了close 发现 没有关闭完全,下一次显示为closeing ,timer 不会更新,再次轮到时发生了阻塞? 应该是我的逻辑状态转换有问题 … …

libuv 的热度 >>>>> libevent ,轻量级又高效

综上述情况的修改

#include <arpa/inet.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>

#define DEFAULT_PORT 4080
#define DEFAULT_BACKLOG 128

void on_close(uv_handle_t *handle) {
  free(handle);
  handle = 0;
}
struct network_client {
  bool alive;
  struct sockaddr_in addr;
  int32_t index;
  char buf[4096];
};

struct network {
  int32_t n_client;
  struct network_client client[255];
};

void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
  uv_handle_t *handle = (uv_handle_t *)client;
  struct network_client *net = client->data;
  uv_shutdown_t showdown;
  if (nread > 0) {
    nread = nread > 4096 ? 4096 : nread;
    net->alive = true;
    memcpy(net->buf, buf->base, nread);
  } else if (nread <= 0) {
    if (!uv_is_closing(handle)) {
      uv_close(handle, on_close);
    }
  }
}

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
  static char buffer[4096];
  bzero(buffer, sizeof(buffer));
  buf->base = buffer;
  buf->len = 4096;
}

void on_new_connection(uv_stream_t *server, int status) {
  if (status < 0) {
    fprintf(stderr, "New connection error %s\n", uv_strerror(status));
    return;
  }
  struct network *center = server->data;
  center->n_client++;
  if (center->n_client >= sizeof(center->client) / sizeof(center->client[0])) {
    center->n_client = 0;
  }

  uv_tcp_t *client = calloc(sizeof(uv_tcp_t), 1);
  int32_t *index = &center->n_client;
  center->client[*index].index = *index;
  client->data = &center->client[*index];
  uv_tcp_init(server->loop, client);
  if (uv_accept(server, (uv_stream_t *)client) == 0) {
    int32_t len = sizeof(struct sockaddr);
    // TODO: get accept addr information
    uv_tcp_getpeername(client, (struct sockaddr *)&center->client[*index].addr,
                       &len);
    uv_read_start((uv_stream_t *)client, server->alloc_cb, server->read_cb);
  } else {
    if (!uv_is_closing((uv_handle_t *)client)) {
      uv_close((uv_handle_t *)client, on_close);
    }
  }
}

int32_t network_deal(struct network *center) {
  for (int32_t i = 0; i < 255; i++) {
    if (center->client[i].alive) {
      printf("index:%d %s: %s\n", i, inet_ntoa(center->client[i].addr.sin_addr),
             center->client[i].buf);
      center->client[i].alive = false;
      center->n_client--;
    }
  }
  return 0;
}

#include <stdlib.h>
#include <time.h>
#include <unistd.h>

void *run(void *args) {
  while (1) {
    while (((struct network *)args)->n_client == 0) {
      usleep(500);
    }
    network_deal(args);
  }
}

int main() {
  struct network net;
  uv_loop_t *loop;
  loop = uv_default_loop();
  uv_tcp_t server;
  struct sockaddr_in addr;
  uv_tcp_init(loop, &server);
  uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
  uv_tcp_bind(&server, (const struct sockaddr *)&addr, 0);
  server.data = &net;
  server.loop = loop;
  server.alloc_cb = alloc_buffer;
  server.read_cb = echo_read;
  int r = uv_listen((uv_stream_t *)&server, DEFAULT_BACKLOG, on_new_connection);
  if (r) {
    fprintf(stderr, "Listen error %s\n", uv_strerror(r));
    return 1;
  }
  pthread_t tid;
  pthread_create(&tid, 0, run, &net);
  return uv_run(loop, UV_RUN_DEFAULT);
}

回射UUID 比对,消息的命中率

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

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

相关文章

MySQL单表查询操作(SELECT语句)

目录 步骤 1、创建表单 2、添加数据 3、显示所有职工的基本信息 4、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号 5、 求出所有职工的人数 6、 列出最高工资和最低工资 7、 列出职工的平均工资和总工资 8、 创建一个只有职工号、姓名和参加工作的新表&a…

Kafka3.0.0版本——Broker(服役新节点)示例

目录 一、服务器信息二、VMware克隆服务节点&#xff08;将虚拟机1克隆成虚拟机4 &#xff09;三、克隆后的&#xff08;192.168.136.30&#xff09;服务节点配置文件修改3.1、修改zookeeper服务配置文件3.2、修改kafka服务配置文件3.3、先启动zookeeper&#xff0c;再启动kafk…

Cesium中通过射线计算日照

Cesium中通过射线计算日照 前段时间接触到一个需求&#xff0c;需要实时的计算建筑的日照&#xff0c;通常优先通过shadow map来实现。通过shadow map可以直接获取某一时刻的光照信息&#xff0c;累积不同太阳光位置的shadow map即可得到物体表面的光照时长。 不过本人技术有限…

Pycharm如何打断点进行调试?

断点调试&#xff0c;是编写程序中一个很重要的步骤&#xff0c;有些简单的程序使用print语句就可看出问题&#xff0c;而比较复杂的程序&#xff0c;函数和变量较多的情况下&#xff0c;这时候就需要打断点了&#xff0c;更容易定位问题。 一、添加断点 在代码的行标前面&…

C++/Qt 读写文件

之前写过两篇跟文件操作相关的博客&#xff0c;有兴趣也可以看一下&#xff1a; C语言读写文件 Qt关于文件路径的处理 先讲一些关于基础文本文件和二进制文件的读写操作&#xff0c;后续将会整理C/Qt关于ini、xml、json、xlsx相关文件的读写操作。 C 相比于C语言使用FILE文…

centos7安装phpipam1.4

by:铁乐与猫 date&#xff1a;2021-5-11 安装依赖 sudo yum install epel-release sudo yum install php-mcrypt安装 Apache, MySQL, PHP (LAMP) stack packages sudo yum install httpd mariadb-server php php-cli php-gd php-common php-ldap php-pdo php-pear php-snmp …

c++11 标准模板(STL)(std::basic_fstream)(三)

定义于头文件 <fstream> template< class CharT, class Traits std::char_traits<CharT> > class basic_fstream : public std::basic_iostream<CharT, Traits> 类模板 basic_fstream 实现基于文件的流上的高层输入/输出。它将 std::basic_i…

JPA实现存储实体类型信息

本文已收录于专栏 《Java》 目录 背景介绍概念说明DiscriminatorValue 注解&#xff1a;DiscriminatorColumn 注解&#xff1a;Inheritance(strategy InheritanceType.SINGLE_TABLE) 注解&#xff1a; 实现方式父类子类执行效果 总结提升 背景介绍 在我们项目开发的过程中经常…

Node RESTful API说明

1、什么是 REST REST即表述性状态传递&#xff1b; 表述性状态转移是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。需要注意的是&#xff0c;REST是设计风格而不是标准。 2、HTTP 方法 以下为 REST 基本架构的四个方法&#xff1a; GET - …

机器视觉项目流程和学习方法

机器视觉项目流程&#xff1a; 00001. 需求分析和方案建立 00002. 算法流程规划和业务逻辑设计 00003. 模块化编程和集成化实现 00004. 调试和优化&#xff0c;交付客户及文档 学习机器视觉的方法&#xff1a; 00001. 实战学习&#xff0c;结合项目经验教训 00002. 学习…

【Leetcode】基础题||合并有序表(击败100%)

step by step. 题目&#xff1a;&#xff08;超级基础的题&#xff09; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例…

mysql统计近7天数据量,,按时间戳分组

可以使用以下 SQL 语句来统计近7天的数据量&#xff0c;并按时间戳分组。如果某一天没有数据&#xff0c;则将其填充为0。 SELECT DATE_FORMAT(FROM_UNIXTIME(timestamp), %Y-%m-%d) AS date,COUNT(*) AS count FROM table_name WHERE timestamp > UNIX_TIMESTAMP(DATE_SUB…

C++ 引用详解

1.引用的基本语法 &#xff08;1&#xff09;语法形式&#xff1a; 数据类型 &别名 原名 &#xff08;2&#xff09;原理 给一个已有的变量起别名 int main() {int a 10;int& b a;cout << "a" << a << " b" << b &l…

Vector - CAPL - 诊断模块函数(流控制帧)

目录 CanTpIsUseFlowControlBlockSize & CanTpUseFlowControlBlockSize 代码示例 CanTpGetOneFlowControlValue & CanTpSetOneFlowControlValue 代码示例 CanTpGetAckMode & CanTpSetAckMode & CanTpGetAckResult & CanTpSetAckResult 代码示例 CanT…

MySQL5.7数据库、Navicat Premium1.6可视化工具安装教程【详细教程】

文章目录 一、MySQL、Navicat、注册机地址二、安装&#xff08;一&#xff09;、MySQL安装&#xff08;二&#xff09;、Navicat Premium安装&#xff08;三&#xff09;、集活Navicat Premium 三、遇到的问题1、Are you sure your navicat has not beenpatched/modified befor…

android开发之Android 自定义滑动解锁View

自定义滑动解锁View 需求如下&#xff1a; 近期需要做一个类似屏幕滑动解锁的功能&#xff0c;右划开始&#xff0c;左划暂停。 需求效果图如下 实现效果展示 自定义view如下 /** Desc 自定义滑动解锁View Author ZY Mail sunnyfor98gmail.com Date 2021/5/17 11:52 *…

测评HTTP代理的透明匿名?

在我们日常的网络冒险中&#xff0c;你是否曾听说过HTTP代理的透明匿名特性&#xff1f;这些神秘的工具就像是网络世界中的隐身斗士&#xff0c;让我们能够在互联网的迷雾中保护自己的身份和隐私。那么&#xff0c;让我们一起揭开HTTP代理的面纱&#xff0c;探索其中的奥秘吧&a…

opencv安装报错解决方案

菜鸟程序员写代码5分钟&#xff0c;配环境5小时 这里记录一下opencv配置报错&#xff0c;其实之前碰到过很多遍了 情况1&#xff1a;安装的时候卡在这一块 Building wheel for opencv-python (pyproject.toml) 解决方案&#xff1a;在安装指令后加--verbose pip install o…

并发三大特性和JMM

一、并发三大特性 1、原子性 一个或多个操作&#xff0c;要么全部执行且在执行过程中不被任何因素打断&#xff0c;要么全部不执行。在Java中&#xff0c;对基本数据类型的读取和赋值操作是原子性操作&#xff08;64位处理器&#xff09;。不采取任何的原子性保障措施的自增操…

微信小程序 map地图(轨迹)

allMarkers效果图 废话少说直接上马&#xff08;最后是我遇到的问题&#xff09; cover-view是气泡弹窗&#xff0c;可以自定义弹窗&#xff0c;要配合js&#xff1a;customCallout&#xff0c;如果是非自定义的话&#xff1a;callout&#xff08;可以修改颜色、边框宽度、圆角…