一.服务端
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)
{
tcpClient::client_send("nizhidoade"+std::to_string(rand()));
Sleep(1000);
}
else
{
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));
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;
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++初学者写的代码,不规范处请见谅。
|