当前位置:网站首页>Libuv框架echo-server.c源码详解(TCP部分)
Libuv框架echo-server.c源码详解(TCP部分)
2022-06-28 06:46:00 【ufgnix0802】
Libuv框架echo-server.c源码详解(TCP部分)
echo-server.c文件是Libuv框架中入门级示例,由官方提供。关于echo-server.c文件如何寻找,可以参考链接:https://blog.csdn.net/qq135595696/article/details/125475334?spm=1001.2014.3001.5501
效果展示
客户端使用sokit工具进行演示。

运行Libuv框架的echo-server.c文件,效果如下:

源码
main.c(关于Libuv环境搭建也可参考文章开头的链接)
#include "uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
static uv_loop_t* loop;//事件循环机制
static uv_handle_t* server;//服务端句柄
static uv_tcp_t tcpServer;//TCP服务端句柄结构体
static stream_type serverType;//服务端服务类型
//发送缓冲区
typedef struct
{
uv_write_t req;
uv_buf_t buf;
}write_req_t;
static void uv_close(uv_handle_t* peer)
{
free(peer);
}
//关闭当前客户端之后的回调响应事件
static void after_shutdown(uv_shutdown_t* req, int status)
{
ASSERT_EQ(status, 0);
uv_close((uv_handle_t*)req->handle, uv_close);
free(req);
}
//向客户端发送消息之后的回调事件
static void after_write(uv_write_t* req, int status)
{
write_req_t* wr;
/*Free the read/write buffer and the request*/
wr = (write_req_t*)req;
free(wr->buf.base);
free(wr);
if (status == 0)
return;
fprintf(stderr, "uv_write error:%s - %s\n",
uv_err_name(status),
uv_strerror(status));
}
//开辟缓冲区大小
static void echo_alloc(uv_handle_t* handle,
size_t suggested_size,
uv_buf_t* buf)
{
buf->base = malloc(suggested_size);
buf->len = suggested_size;
}
//接收客户端数据之后的响应事件
static void after_read(uv_stream_t* handle,
ssize_t nread,//读取到的数据长度
const uv_buf_t* buf)
{
//关闭客户端事件
uv_shutdown_t* sreq;
//写事件
write_req_t* wr;
//读取数据失败
if (nread < 0)
{
/*Error or EOF*/
ASSERT_EQ(nread, UV_EOF);
free(buf->base);
sreq = malloc(sizeof * sreq);
//检查当前客户端是否可写
if (uv_is_writable(handle))
{
//关闭当前客户端,并注册关闭当前客户端后的响应回调事件
ASSERT_EQ(0, uv_shutdown(sreq, handle, after_shutdown));
}
return;
}
//没有可读消息
if (nread == 0)
{
/*Everything OK,but nothing read.*/
free(buf->base);
return;
}
//处理客户端消息
wr = (write_req_t*)malloc(sizeof * wr);
ASSERT_NOT_NULL(wr);
//初始化发送缓冲区
wr->buf = uv_buf_init(buf->base, nread);
//向客户端发送消息,并注册发送消息之后的回调事件
if (uv_write(&wr->req, handle, &wr->buf, 1, after_write))
{
FATAL("uv_write failed");
}
}
//客户端连接到来的响应回调函数
static void on_connection(uv_stream_t* server, int status)
{
uv_stream_t* stream;
int r;
if (status != 0)
fprintf(stderr, "Connect error %s\n", uv_err_name(status));
ASSERT(status == 0);
switch (serverType)
{
case TCP:
stream = malloc(sizeof(uv_tcp_t));//创建流来管理当前接收的客户端
ASSERT_NOT_NULL(stream);
r = uv_tcp_init(loop, (uv_tcp_t*)stream);//将客户端与当前loop(事件循环机制)关联
ASSERT(r == 0);
break;
default:
ASSERT(0 && "Bad serverType");
abort();
}
/* associate server with stream,将客户端和当前服务端关联 */
stream->data = server;
r = uv_accept(server, stream);//接收到来的客户端
ASSERT(r == 0);
//接收客户端发送的消息,并注册接收客户端消息之后的回调响应事件和分配接收缓冲区大小回调事件
r = uv_read_start(stream, echo_alloc, after_read);
ASSERT(r == 0);
}
static int tcp4_echo_start(int port)
{
struct sockaddr_in addr;
int r;
//如果跟0相等,那么就继续执行
//设置IP地址和端口号
ASSERT(0 == uv_ip4_addr("127.0.0.1", port, &addr));
server = (uv_handle_t*)&tcpServer;
serverType = TCP;
r = uv_tcp_init(loop, &tcpServer);//初始化并创建socket
if (r)
{
/* TODO:Error codes*/
fprintf(stderr, "Socket creation error\n");
return 1;
}
r = uv_tcp_bind(&tcpServer, (const struct sockaddr*)&addr, 0);//把socket跟IP和端口号绑定
if (r)
{
/*TODO:Error codes*/
fprintf(stderr, "Bind error\n");
return 1;
}
r = uv_listen((uv_stream_t*)&tcpServer, SOMAXCONN, on_connection);//监听端口,接收客户端连接并注册客户端到来后的响应回调事件
if (r)
{
/*TODO:Error codes*/
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
return 1;
}
return 0;
}
int main()
{
loop = uv_default_loop();//初始化事件循环机制
//创建服务端
if (tcp4_echo_start(TEST_PORT))
return 1;
//启动事件循环机制
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}
边栏推荐
猜你喜欢

推荐10个好用到爆的Jupyter Notebook插件,让你效率飞起

FPGA - 7系列 FPGA SelectIO -08- 高级逻辑资源之OSERDESE2

Error reporting - resolve core JS / modules / es error. cause. JS error

Paper recommendation: efficientnetv2 - get smaller models and faster training speed through NAS, scaling and fused mbconv

Batch import of pictures into WPS table by date

D3D11_ Chili_ Tutorial (3): design a bindable/drawable system
![[online tutorial] official iptables tutorial -- learning notes 1](/img/b9/8f94caa46eb46dab581c713494f36d.png)
[online tutorial] official iptables tutorial -- learning notes 1

JS regular expression system explanation (comprehensive summary)

FPGA - 7 Series FPGA selectio -08- oserdese2 of advanced logic resources

链表(一)——移除链表元素
随机推荐
选拔赛题目代码
Yolov5 adds a small target detection layer
Integer promotion and size side byte order
Puge -- understanding of getordefault() method
[produced by Xinghai] operation and maintenance inspection collection
[interval DP] stone consolidation
js正则表达式系统讲解(全面的总结)
freeswitch设置最大呼叫时长
Rust FFI 编程 - libc crate
Singleton singleton mode
推荐10个好用到爆的Jupyter Notebook插件,让你效率飞起
MySQL (II) - basic operation
5-minute NLP: summary of time chronology from bag of words to transformer
KMP string
Online facing such an online world, the only limitation is our imagination
Batch import of pictures into WPS table by date
AutoCAD C# 多段線小銳角檢測
Interpretation of Blog
ImportError: cannot import name 'ensure_ dir_ Possible solutions for exists'
4~20mA输入/0~5V输出的I/V转换电路