是否可以在2个不同的端口上安装2个WinSock服务器?

时间:2014-12-25 09:59:11

标签: c++ winsock

我有一个简单的问题,我有一个tcp代理服务器,它帮助我将数据从1端口重定向到另一个,即:55500到55510,现在我想让服务器听另一个端口,让我们说55520 ,所有这一切同时,是否可能? 我试过这里找到绑定到另一个端口的例子,但也许我做错了什么:( 我在启动代理服务器后试图创建一个IOCP服务器,但它崩溃了......任何想法?或者也许是一个例子?任何帮助都会被贬低!

这是我的proxytcp:

#include "ProxyTCP.h"
#include <process.h>
#include "GInclude.h"
using namespace std;


CProxyTCP::CProxyTCP() : 
    _guid(0),
    _started(false), 
    _hevent_start(NULL),
    _hevent_stop(NULL),
    _serv_sock(INVALID_SOCKET),
    _connect_callback(NULL),
    _connect_param(NULL),
    _close_callback(NULL),
    _close_param(NULL),
    _send_callback(NULL),
    _send_param(NULL),
    _recv_callback(NULL),
    _recv_param(NULL)
{
    InitializeCriticalSection(&_csect);
    InitializeCriticalSection(&_csect_dbg);
}

CProxyTCP::~CProxyTCP()
{
    Stop();
    DeleteCriticalSection(&_csect);
    DeleteCriticalSection(&_csect_dbg);
}

bool CProxyTCP::Start(const char *src_addr, unsigned short src_port, const char *dest_addr, unsigned short dest_port)
{
    sockaddr_in addr = {};
    int res;

    if (_started) {
        _DBG_OUTPUT("Error, server already started!");
        return false;
    }

    RemoveAllConnInfo();
    _removed_conn.clear();
    _hthr_pool.clear();

    if (!CreateSockAddr(src_addr, src_port, &addr)) {
        _DBG_OUTPUT("Error, incorrect source address");
        return false;
    }
    if (!dest_addr || !CreateSockAddr(dest_addr, dest_port, &_serv_addr)) {
        _DBG_OUTPUT("Error, incorrect destination address");
        return false;
    }

    _serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (_serv_sock == INVALID_SOCKET) {
        _DBG_OUTPUT("Error, socket() failed with code " << WSAGetLastError());
        return false;
    }

    res = bind(_serv_sock, (sockaddr *)&addr, sizeof(addr));
    if (res == SOCKET_ERROR) {
        _DBG_OUTPUT("Error, bind() failed with code " << WSAGetLastError());
        closesocket(_serv_sock);
        return false;
    }

    _hevent_start = CreateEvent(NULL, true, false, NULL);
    if (!_hevent_start) {
        _DBG_OUTPUT("Error, CreateEvent() failed with code " << GetLastError());
        closesocket(_serv_sock);
        return false;
    }

    _hevent_stop = CreateEvent(NULL, true, true, NULL);
    if (!_hevent_start) {
        _DBG_OUTPUT("Error, CreateEvent() failed with code " << GetLastError());
        CloseHandle(_hevent_start);
        closesocket(_serv_sock);
        return false;
    }

    _started = true;

    _beginthreadex(NULL, 0, proxy_conn_gate, this, 0, NULL);

    if (WaitForSingleObject(_hevent_start, 10000) != WAIT_OBJECT_0) {
        _DBG_OUTPUT("Error, WaitForSingleObject() failed");
        Stop();
        return false;
    }

    return true;
}

void CProxyTCP::Stop()
{
    bool retn = false;
    HANDLE *pthr_pool;
    unsigned int count;

    EnterCriticalSection(&_csect);
    if (!_started) {
        retn = true;
    } else {
        _started = false;
    }
    LeaveCriticalSection(&_csect);
    if (retn) {
        return;
    }

    if (_serv_sock != INVALID_SOCKET) {
        closesocket(_serv_sock);
        _serv_sock = INVALID_SOCKET;
    }

    WaitForSingleObject(_hevent_stop, INFINITE);

    EnterCriticalSection(&_csect);
    count = _hthr_pool.size() * 2;
    if (count != 0) {
        try {
            pthr_pool = new HANDLE[count];
        } catch (...) {
            pthr_pool = NULL;
        }

        map<unsigned int, std::pair<HANDLE, HANDLE>>::iterator it = _hthr_pool.begin();
        for (unsigned int i = 0; i < count; i += 2, it++) {
            pthr_pool[i] = it->second.first;
            pthr_pool[i + 1] = it->second.second;
        }

        list<PProxy_Client>::iterator it_conn = _conn.begin();
        PProxy_Client pelem;
        for (unsigned int i = 0; i < _conn.size(); i++, it_conn++) {
            pelem = *it_conn;
            closesocket(pelem->client);
            closesocket(pelem->server);
        }
    }
    LeaveCriticalSection(&_csect);

    if (count == 0) {
        return;
    }

    if (pthr_pool == NULL) {
        Sleep(2000); //hmm...
    } else {
        WaitForMultipleObjects(count, pthr_pool, true, 2000);
    }

    RemoveAllConnInfo();
}

bool CProxyTCP::IsStarted()
{
    return _started;
}

void CProxyTCP::RegConnectFilter(tcp_proxy_connect_filter callback, void *param)
{
    _connect_callback = callback;
    _connect_param = param;
}

void CProxyTCP::UnregConnectFilter()
{
    _connect_callback = NULL;
    _connect_param = NULL;
}

void CProxyTCP::RegCloseFilter(tcp_proxy_close_filter callback, void *param)
{
    _close_callback = callback;
    _close_param = param;
}

void CProxyTCP::UnregCloseFilter()
{
    _close_callback = NULL;
    _close_param = NULL;
}

void CProxyTCP::RegSendFilter(tcp_proxy_traffic_filter callback, void *param)
{
    _send_callback = callback;
    _send_param = param;
}

void CProxyTCP::UnregSendFilter()
{
    _send_callback = NULL;
    _send_param = NULL;
}

void CProxyTCP::RegRecvFilter(tcp_proxy_traffic_filter callback, void *param)
{
    _recv_callback = callback;
    _recv_param = param;
}

void CProxyTCP::UnregRecvFilter()
{
    _recv_callback = NULL;
    _recv_param = NULL;
}

bool CProxyTCP::CreateSockAddr(const char *addr, unsigned short port, sockaddr_in *psaddr)
{
    psaddr->sin_family = AF_INET;
    psaddr->sin_port = htons(port);

    if (!addr) {
        psaddr->sin_addr.s_addr = 0;
    } else {
        psaddr->sin_addr.s_addr = inet_addr(addr);
        if (psaddr->sin_addr.s_addr == INADDR_NONE) {
            HOSTENT *host;
            host = gethostbyname(addr);
            if (!host) {
                return false;
            }
            psaddr->sin_addr.s_addr = host->h_addr[0];
        }
    }

    return true;
}

unsigned int CProxyTCP::AddConnInfo(SOCKET client)
{
    PProxy_Client pelem = new Proxy_Client;

    EnterCriticalSection(&_csect);

    __try {
        pelem->id = GenGuid();
        pelem->client = client;
        pelem->server = INVALID_SOCKET;
        pelem->client_init = false;
        pelem->server_init = false;
        pelem->started = false;

        pelem->hevent_init = CreateEvent(NULL, false, false, NULL);
        if (!pelem->hevent_init) {
            delete pelem;
            return INVALID_CONN_ID;
        }

        pelem->hevent_sync = CreateEvent(NULL, false, false, NULL);
        if (!pelem->hevent_sync) {
            CloseHandle(pelem->hevent_init);
            delete pelem;
            return INVALID_CONN_ID;
        }

        _conn.push_back(pelem);

    } __finally {
        LeaveCriticalSection(&_csect);
    }

    return pelem->id;
}

CProxyTCP::PProxy_Client CProxyTCP::GetFreeClientConnInfo()
{
    list<PProxy_Client>::iterator it;
    PProxy_Client pelem = NULL;

    EnterCriticalSection(&_csect);

    it = _conn.begin();
    while (it != _conn.end()) {
        if ((*it)->client_init == false) {
            pelem = (*it);
            pelem->client_init = true;
            break;
        }
        it++;
    }

    LeaveCriticalSection(&_csect);

    return pelem;
}

CProxyTCP::PProxy_Client CProxyTCP::GetFreeServerConnInfo()
{
    list<PProxy_Client>::iterator it;
    PProxy_Client pelem = NULL;

    EnterCriticalSection(&_csect);

    it = _conn.begin();
    while (it != _conn.end()) {
        if ((*it)->server_init == false) {
            pelem = (*it);
            pelem->server_init = true;
            break;
        }
        it++;
    }

    LeaveCriticalSection(&_csect);

    return pelem;
}

bool CProxyTCP::RemoveConnInfo(unsigned int conn_id)
{
    list<PProxy_Client>::iterator it;
    bool res = false;

    EnterCriticalSection(&_csect);

    it = _conn.begin();
    while (it != _conn.end()) {
        if ((*it)->id == conn_id) {
            (*it)->started = false;

            if ((*it)->client) {
                closesocket((*it)->client);
            }
            if ((*it)->server) {
                closesocket((*it)->server);
            }
            if ((*it)->hevent_sync) {
                SetEvent((*it)->hevent_sync);
                CloseHandle((*it)->hevent_sync);
            }
            if ((*it)->hevent_init) {
                SetEvent((*it)->hevent_init);
                CloseHandle((*it)->hevent_init);
            }

            _conn.erase(it);
            res = true;
            break;
        }
        it++;
    }

    LeaveCriticalSection(&_csect);

    return res;
}

void CProxyTCP::RemoveAllConnInfo()
{
    list<PProxy_Client>::iterator it;

    EnterCriticalSection(&_csect);

    it = _conn.begin();
    while (it != _conn.end()) {
        (*it)->started = false;

        if ((*it)->client) {
            closesocket((*it)->client);
        }
        if ((*it)->server) {
            closesocket((*it)->server);
        }
        if ((*it)->hevent_sync) {
            SetEvent((*it)->hevent_sync);
            CloseHandle((*it)->hevent_sync);
        }
        if ((*it)->hevent_init) {
            SetEvent((*it)->hevent_init);
            CloseHandle((*it)->hevent_init);
        }

        it++;
    }

    LeaveCriticalSection(&_csect);
}

void CProxyTCP::ClearClosedResources()
{
    list<unsigned int>::iterator it;

    EnterCriticalSection(&_csect);
    it = _removed_conn.begin();
    while (it != _removed_conn.end()) {
        _hthr_pool.erase(*it);
        it++;
    }
    LeaveCriticalSection(&_csect);
}

void CProxyTCP::ConnectionCtrl()
{
    SOCKET client_sock = INVALID_SOCKET;
    HANDLE hthr_client, hthr_server;
    sockaddr_in saddr;
    unsigned int id;
    int res;

    ResetEvent(_hevent_stop);
    SetEvent(_hevent_start);

    while (_started) {
        res = listen(_serv_sock, SOMAXCONN);
        if (res == SOCKET_ERROR) {
            _DBG_OUTPUT("Error, ConnectionCtrl::listen() failed with code " << res);
            break;
        }

        client_sock = accept(_serv_sock, (sockaddr *)&saddr, NULL);
        if (client_sock == INVALID_SOCKET) {
            continue;
        }

        id = AddConnInfo(client_sock);
        if (id == INVALID_CONN_ID) {
            _DBG_OUTPUT("Error, ConnectionCtrl::AddConnInfo() failed");
            continue;
        }

        if (_connect_callback) {
            if (!_connect_callback(id, &saddr, _connect_param)) {
                RemoveConnInfo(id);
                closesocket(client_sock);
                continue;
            }
        }

        //SOCKADDR_IN client_info = {0};
        //int addrsize = sizeof(client_info);
        //getpeername(client_sock, &saddr, sizeof(saddr));

//      char *ip = inet_ntoa(saddr.sin_addr);
//g_Log.LogAdd(g_Colors.Gold(), "test %s", ip);
        //_DBG_OUTPUT(">>>> Client #" << id << " connected");

        EnterCriticalSection(&_csect);

        hthr_client = (HANDLE)_beginthreadex(NULL, 0, proxy_send_gate, this, 0, NULL);
        hthr_server = (HANDLE)_beginthreadex(NULL, 0, proxy_recv_gate, this, 0, NULL);

        _hthr_pool.insert(
            pair<unsigned int, pair<HANDLE, HANDLE>>(
                id, pair<HANDLE, HANDLE>(hthr_client, hthr_server)
            )
        );

        LeaveCriticalSection(&_csect);

        ClearClosedResources();
    }

    SetEvent(_hevent_stop);
}

void CProxyTCP::SendCtrl(PProxy_Client client)
{
    enum { MAX_BUF_LEN = 2048 };
    char recvbuf[MAX_BUF_LEN];
    int res;

    res = WaitForSingleObject(client->hevent_sync, 10000);
    if (res != WAIT_OBJECT_0) {
        _DBG_OUTPUT("Error, SendCtrl::WaitForSingleObject() failed with code " << GetLastError());
        return;
    }

    //init
    /*for(ptr = _serv_addr; ptr != NULL; ptr = ptr->ai_next) {
        client->server = socket(_serv_addr->ai_family, _serv_addr->ai_socktype, _serv_addr->ai_protocol);
        if (client->server == INVALID_SOCKET) {
            _DBG_OUTPUT("Error, SendCtrl::socket() failed with code " << WSAGetLastError());
            return;
        }

        res = connect(client->server, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (res == SOCKET_ERROR) {
            closesocket(client->server);
            client->server = INVALID_SOCKET;
            continue;
        }

        break;
    }
    if (client->server == INVALID_SOCKET) {
        return;
    }*/
    client->server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (client->server == INVALID_SOCKET) {
        _DBG_OUTPUT("Error, SendCtrl::socket() failed with code " << WSAGetLastError());
        return;
    }

    res = connect(client->server, (sockaddr *)&_serv_addr, sizeof(_serv_addr));
    if (res == SOCKET_ERROR) {
        _DBG_OUTPUT("Error, SendCtrl::connect() failed with code " << WSAGetLastError());
        closesocket(client->server);
        client->server = INVALID_SOCKET;
        return;
    }

    client->started = true;
    SetEvent(client->hevent_init);

    //worked cycle
    while (client->started && _started) {
        res = recv(client->client, recvbuf, MAX_BUF_LEN, 0);
        if (res == 0) {
            break;
        } else if (res < 0) {
            break;
        }

        if (_send_callback) {
            res = _send_callback(client->id, recvbuf, res, MAX_BUF_LEN, _send_param);
            if (res == 0) {
                break;
            } else if (res < 0) {
                break;
            }
        }

        res = send(client->server, recvbuf, res, 0);
        if (res == SOCKET_ERROR) {
            break;
        }
    }

    client->started = false;
    closesocket(client->client);
    closesocket(client->server);

    WaitForSingleObject(client->hevent_sync, 10000);

    if (_close_callback) {
        _close_callback(client->id, _close_param);
    }

    EnterCriticalSection(&_csect);
    _removed_conn.insert(_removed_conn.begin(), client->id);
    LeaveCriticalSection(&_csect);

    //_DBG_OUTPUT("<<<< Client #" << client->id << " closed");
}

void CProxyTCP::RecvCtrl(PProxy_Client client)
{
    enum { MAX_BUF_LEN = 2048 };
    char recvbuf[MAX_BUF_LEN];
    int res;

    SetEvent(client->hevent_sync);

    res = WaitForSingleObject(client->hevent_init, 10000);
    if (res != WAIT_OBJECT_0) {
        _DBG_OUTPUT("Error, RecvCtrl::WaitForSingleObject() failed with code " << GetLastError());
        return;
    }

    //worked cycle
    while (client->started && _started) {
        res = recv(client->server, recvbuf, MAX_BUF_LEN, 0);
        if (res == 0) {
            break;
        } else if (res < 0) {
            break;
        }

        if (_recv_callback) {
            res = _recv_callback(client->id, recvbuf, res, MAX_BUF_LEN, _recv_param);
            if (res == 0) {
                break;
            } else if (res < 0) {
                break;
            }
        }

        res = send(client->client, recvbuf, res, 0);
        if (res == SOCKET_ERROR) {
            break;
        }
    }

    client->started = false;

    SetEvent(client->hevent_sync);
}

unsigned int __stdcall CProxyTCP::proxy_conn_gate(void *param)
{
    CProxyTCP *pthis = (CProxyTCP *)param;

    pthis->ConnectionCtrl();
    pthis->Stop();

    _endthreadex(0);
    return 0;
}

unsigned int __stdcall CProxyTCP::proxy_send_gate(void *param)
{
    CProxyTCP *pthis = (CProxyTCP *)param;
    PProxy_Client client;

    client = pthis->GetFreeServerConnInfo();
    if (!client) {
        _endthreadex(1);
        return 1;
    }

    pthis->SendCtrl(client);
    pthis->RemoveConnInfo(client->id);

    _endthreadex(0);
    return 0;
}

unsigned int __stdcall CProxyTCP::proxy_recv_gate(void *param)
{
    CProxyTCP *pthis = (CProxyTCP *)param;
    PProxy_Client client;

    client = pthis->GetFreeClientConnInfo();
    if (!client) {
        _endthreadex(1);
        return 1;
    }

    pthis->RecvCtrl(client);

    _endthreadex(0);
    return 0;
}

0 个答案:

没有答案