找到了一份示例代码.根据实际情况做了修改
#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 = ¢er->n_client;
center->client[*index].index = *index;
center->client[*index].client.data = ¢er->client[*index];
uv_tcp_init(server->loop, ¢er->client[*index].client);
if (uv_accept(server, (uv_stream_t *)¢er->client[*index].client) == 0) {
int32_t len = sizeof(struct sockaddr);
// TODO: get accept addr information
uv_tcp_getpeername(¢er->client[*index].client,
(struct sockaddr *)¢er->client[*index].addr, &len);
uv_read_start((uv_stream_t *)¢er->client[*index].client,
server->alloc_cb, server->read_cb);
} else {
uv_close((uv_handle_t *)¢er->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 = ¢er->n_client;
center->client[*index].index = *index;
client->data = ¢er->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 *)¢er->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 比对,消息的命中率