libuv实现tcp代理服务器

概述

为了学习libuv的tcp相关函数使用,实现了一个tcp代理服务。

1 启动TCP服务
2 如果有新的连接X,则向代理地址建立连接Y,并关联X和Y成组
3 如果X收到数据包,发往Y;反之如果Y收到数据包发往X
4 如果X或者Y连接异常,关闭此组连接
5 代理服务退出时,清理所有组,清理TCP服务

API简介

uv_err_name

出现错误可以通过uv_strerror和uv_err_name找错误原因。

int r = uv_accept(server, stream);
fprintf(stderr, "uv_accept error %s\n", uv_err_name(r));

uv_ip4_addr

struct sockaddr_in m_local;
struct sockaddr_in m_remote;
...
uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &m_local);

将给定的ip地址和端口转换成sockaddr_in结构体,原生编程的时候,设置ip和端口需要至少五行,用这个方法可以简化操作

uv_tcp_init

初始化 tcp 对象

uv_loop_t* m_loop;
...
m_loop = uv_default_loop();
...
uv_tcp_t m_tcpServer;
...
uv_tcp_init(m_loop, &m_tcpServer);//初始化tcp server对象

uv_tcp_bind

等同于原生API的 bind() 方法

uv_tcp_bind(&m_tcpServer, (const struct sockaddr*) &m_local, 0);

uv_tcp_bind() 的第三个参数 flag 一般是0,如果想使用IP6,可以使用 UV_TCP_IPV6ONLY

enum uv_tcp_flags {
   
  /* Used with uv_tcp_bind, when an IPv6 address is used. */
  UV_TCP_IPV6ONLY = 1
};

uv_listen

与listen作用类似,增加了回调函数,有新连接来时会触发回调。

uv_listen((uv_stream_t*)&m_tcpServer, 50, OnAccept);

uv_accept

在OnAccept回调中执行uv_accept,用socket与stream关联,stream需要先分配内存和初始化。

int r;
uv_stream_t* stream;
...
uv_tcp_init(pProxy->m_loop, (uv_tcp_t*) stream);
...
r = uv_accept(server, stream);
uv_err_name(r)

源码演示

//
/*
在入口函数中包含 _CrtDumpMemoryLeaks();  
即可检测到内存泄露
*/
#define CRTDBG_MAP_ALLOC  
#include <stdlib.h>  
#include <crtdbg.h>  
//

#include <conio.h>    //for kbhit()
#include "stdafx.h"
#include "uv.h"
#include <map>
#include <algorithm>
using namespace std;

#define container_of(ptr, type, member) \
    ((type *) ((char *) (ptr) - offsetof(type, member)))

typedef void* (*proc_func)(char* buff, size_t size);

class CProxy
{
   
public:
    CProxy(const char* sip, int sport, const char* dip, int dport, uv_loop_t* loop = NULL)
    {
   
        uv_ip4_addr(sip, sport, &m_local);
        uv_ip4_addr(dip, dport, &m_remote);
        if (NULL == loop)
        {
   
            m_loop = uv_default_loop();
        }
        else
        {
   
            m_loop = loop;
        }
    }

    int Start()
    {
   
        int r = 0;
        
        r = uv_tcp_init(m_loop, &m_tcpServer);
        if (r)
        {
   
            return r;
        }

        r = uv_tcp_bind(&m_tcpServer, (const struct sockaddr*) &m_local, 0);
        if (r)
        {
   
            uv_err_name(r);
            return r;
        }

        r = uv_listen((uv_stream_t*)&m_tcpServer, 50, OnAccept);
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值