当前位置:网站首页>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;
}
边栏推荐
- FPGA - 7系列 FPGA SelectIO -08- 高级逻辑资源之OSERDESE2
- freeswitch使用mod_shout模块播放mp3
- 手把手教你用Ucos
- Caused by: com. fasterxml. jackson. databind. Exc.invalidformatexception: exception resolution
- @RequestParam
- 报错--解决core-js/modules/es.error.cause.js报错
- 强化学习——格子世界
- JDBC learning (I) -- implementing simple CRUD operations
- 异常处理(一)——空指针和数组索引越界
- Drop down list processing in Web Automation
猜你喜欢

JDBC learning (I) -- implementing simple CRUD operations

「杰伦熊」暴跌96.6% 明星带货NFT为何遇冷?

代码没写错,渲染页面不显示原因
![[online tutorial] official iptables tutorial -- learning notes 1](/img/b9/8f94caa46eb46dab581c713494f36d.png)
[online tutorial] official iptables tutorial -- learning notes 1

CAD二次开发+NetTopologySuite+PGIS 引用多版本DLL问题

报错--解决core-js/modules/es.error.cause.js报错

三极管驱动无刷电机

链表(三)——反转链表

AutoCAD C # Polyline Small Sharp angle Detection

AutoCAD C# 多段线小锐角检测
随机推荐
Promotion intégrale et ordre des octets de fin de taille
编译原理期末复习
Alert pop-up processing in Web Automation
整型提昇和大小端字節序
【Paper Reading-3D Detection】Fully Convolutional One-Stage 3D Object Detection on LiDAR Range Images
最后的二十九天
链表(三)——反转链表
Extern "C" overview
Triode driven brushless motor
【Paper Reading-3D Detection】Fully Convolutional One-Stage 3D Object Detection on LiDAR Range Images
Iphone6plus enters the list of antique products netizen: I'm still using it
推荐10个好用到爆的Jupyter Notebook插件,让你效率飞起
助力涨点 | YOLOv5结合Alpha-IoU
Students who do not understand the code can also send their own token. The current universal dividend model can be divided into BSC and any generation B
ROS rviz_ Satellite function package visualizes GNSS track and uses satellite map
CMAKE小知识
微信小程序分页功能,下拉刷新功能,直接干货拿来就用
代码没写错,渲染页面不显示原因
实现这个 issue 得700块钱人民币,有人做嘛?
链表(一)——移除链表元素