IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> libuv的TCP协议客户端和服务端实现 -> 正文阅读

[网络协议]libuv的TCP协议客户端和服务端实现

一.服务端

spdlog记录log不需要的可以直接删除。换成std::cout输出也可以。

#include "tcpService.h"
#include <uv.h>
#include <iostream>
#include <string>
#include "spdlogTools.h"

uv_tcp_t handle;
uv_loop_t* loop;

tcpService::tcpService()
{

}

void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
	spdlogTools::getInstance()->debug("alloc_cb");
	buf->base = (char*)malloc(suggested_size);
	buf->len = suggested_size;
}
void close_cb(uv_handle_t* handle)
{
	spdlogTools::getInstance()->debug("service close_cb");
	delete handle;
}
void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
	spdlogTools::getInstance()->debug("read_cb,nread =  " + std::to_string(nread));
	if (nread > 0)
	{
		std::string realValue = buf->base;
		realValue = realValue.substr(0, nread);
		std::cout << realValue << std::endl;
	}
	else if (nread < 0)
	{
		if (nread == UV_EOF)
		{
			spdlogTools::getInstance()->debug("UV_EOF断开连接");
		}
		else if (nread == UV_ECONNRESET)
		{
			spdlogTools::getInstance()->debug("UV_ECONNRESET");
		}
		uv_close((uv_handle_t*)stream, close_cb);
	}
	if (buf->base)
	{
		free(buf->base);
	}
	

}
void on_new_connection(uv_stream_t* server, int status) 
{
	//连接时调用
	spdlogTools::getInstance()->debug("on_new_connection status: " + status);
	uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
	uv_tcp_init(loop, client);
	if (uv_accept(server, (uv_stream_t*)client) == 0)//接收数据
	{
		uv_read_start((uv_stream_t*)client, alloc_cb, read_cb);
	}
	else
	{
		std::cout << "uv_close" << std::endl;
		uv_close((uv_handle_t*)client, NULL);
	}

}

void tcpService::startTCPService() 
{
	sockaddr_in addr;
	char ip[100];
	std::cout << "请输入服务器地址 : " << std::endl;
	std::cin >> ip;
	uv_ip4_addr(ip, 6789, &addr);
	loop = uv_default_loop();
	uv_tcp_init(loop, &handle);
	uv_tcp_bind(&handle, (const sockaddr*)&addr, 0);
	//监听
	int listen = uv_listen((uv_stream_t*)&handle, 1000, on_new_connection);
	spdlogTools::getInstance()->debug("listen result:  " + std::to_string(listen));
	uv_run(loop, UV_RUN_DEFAULT);
}

tcpService::~tcpService()
{
}

main函数调用

#include "tcpService.h"

int main() 
{
	tcpService::startTCPService();

	return 0;
}

二、客户端

#include "tcpClient.h"
#include <iostream>
#include <uv.h>

uv_tcp_t client;
uv_loop_t* loop;
sockaddr_in serviceAddr;
uv_connect_t* sendReq;
bool isconnect = false;
char serviceIP[100];

void write_cb(uv_write_t* req, int status)
{
	std::cout << "write_cb" + std::to_string(status) << std::endl;
	if (req && status == 0)
	{
		//uv_close((uv_handle_t*)req->handle, NULL);//断开连接
		tcpClient::client_send("nizhidoade"+std::to_string(rand()));
		Sleep(1000);
	}
	else //if (status == UV_ECONNRESET)
	{
		std::cout << "write_cb status = UV_ECONNRESET" << std::endl;
		uv_close((uv_handle_t*)req->handle, NULL);//先断开在重连
		isconnect = false;
		tcpClient::initClient();
		Sleep(1000);
	}
}

void connect_cb(uv_connect_t* req, int status)
{
	isconnect = false;
	if (status == 0)//连接成功
	{
		std::cout << "connect success = " + std::to_string(status) << std::endl;
		isconnect = true;
		sendReq = req;
		uv_buf_t buf;
		std::string message = "message info";
		buf = uv_buf_init((char *)message.data(), message.length());
		uv_buf_t bufs[] = { buf };
		int write = uv_write((uv_write_t*)req, (uv_stream_t*)&client, bufs, 1, write_cb);
		while (write < 0)
		{
			std::cout << "first write error = " + std::to_string(status) << std::endl;
			write = uv_write((uv_write_t*)req, (uv_stream_t*)&client, bufs, 1, write_cb);
			Sleep(1000);
		}
		
	}
	else 
	{
		switch (status)
		{
		case UV_EADDRINUSE:
			std::cout << "address already in use " + std::to_string(status) << std::endl;
		case UV_ETIMEDOUT:
			std::cout << "connection timed out " + std::to_string(status) << std::endl;
		case UV_ENETUNREACH:
			std::cout << "network is unreachable " + std::to_string(status) << std::endl;
		case UV_EHOSTUNREACH:
			std::cout << "host is unreachable " + std::to_string(status) << std::endl;
		case UV_ECONNREFUSED:
			std::cout << "connection refused " + std::to_string(status) << std::endl;
		default:
			break;
		}
		std::cout << "connect error = " + std::to_string(status) << std::endl;
		uv_tcp_connect(req, &client, (const sockaddr*)&serviceAddr, connect_cb);//重连连接服务器端口
		Sleep(1000);
	}
	
}

void tcpClient::initClient() 
{
	loop = uv_default_loop();
	uv_tcp_init(loop, &client);
	sockaddr_in addr;
	int port = 4569;
	std::cout << "port: " + std::to_string(port) << std::endl;
	uv_ip4_addr("192.168.1.1", port, &addr);//本地客户端端口
	uv_tcp_bind(&client, (const sockaddr*)&addr, 0);

	uv_connect_t *connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));
	//sockaddr_in serviceAddr;
	
	if (std::strlen(serviceIP) == 0)
	{
		std::cout << "请输入连接的服务器地址 : " << std::endl;
		std::cin >> serviceIP;
	}
	uv_ip4_addr(serviceIP, 6789, &serviceAddr);
	
	int b =  uv_tcp_connect(connect, &client, (const sockaddr*)&serviceAddr, connect_cb);//连接服务器端口
	std::cout << "uv_tcp_connect: " + std::to_string(b) << std::endl;
	uv_run(loop, UV_RUN_DEFAULT);
}

void tcpClient::client_send(const std::string msg)
{
	uv_buf_t buf;
	//std::string message = "message info";
	buf = uv_buf_init((char *)msg.data(), msg.length());
	uv_buf_t bufs[] = { buf };
	int write = uv_write((uv_write_t*)sendReq, (uv_stream_t*)&client, bufs, 1, write_cb);
	
}


tcpClient::tcpClient()
{
}


tcpClient::~tcpClient()
{
}

客户端main函数调用

#include "tcpClient.h"
#include <iostream>
int main() 
{
	tcpClient::initClient();
	
	std::cin.get();
	return 0;
}

libuv具体TCP协议讲解参阅官方文档:libuv文档

C++初学者写的代码,不规范处请见谅。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:45:03  更:2021-08-17 15:45:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:41:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码