131 lines
3.9 KiB
C++
131 lines
3.9 KiB
C++
/*
|
||
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
|
||
*
|
||
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
|
||
*
|
||
* Use of this source code is governed by MIT license that can be found in the
|
||
* LICENSE file in the root of the source tree. All contributing project authors
|
||
* may be found in the AUTHORS file in the root of the source tree.
|
||
*/
|
||
|
||
#include "UdpClient.h"
|
||
|
||
using namespace std;
|
||
|
||
namespace toolkit {
|
||
|
||
StatisticImp(UdpClient)
|
||
|
||
UdpClient::UdpClient(const EventPoller::Ptr &poller) : SocketHelper(nullptr) {
|
||
setPoller(poller ? poller : EventPollerPool::Instance().getPoller());
|
||
setOnCreateSocket([](const EventPoller::Ptr &poller) {
|
||
//TCP客户端默认开启互斥锁
|
||
return Socket::createSocket(poller, true);
|
||
});
|
||
}
|
||
|
||
UdpClient::~UdpClient() {
|
||
TraceL << "~" << UdpClient::getIdentifier();
|
||
}
|
||
|
||
void UdpClient::startConnect(const string &peer_host, uint16_t peer_port, uint16_t local_port) {
|
||
weak_ptr<UdpClient> weak_self = static_pointer_cast<UdpClient>(shared_from_this());
|
||
_timer = std::make_shared<Timer>(2.0f, [weak_self]() {
|
||
auto strong_self = weak_self.lock();
|
||
if (!strong_self) {
|
||
return false;
|
||
}
|
||
strong_self->onManager();
|
||
return true;
|
||
}, getPoller());
|
||
|
||
setSock(createSocket());
|
||
|
||
auto sock_ptr = getSock().get();
|
||
sock_ptr->setOnErr([weak_self, sock_ptr](const SockException &ex) {
|
||
auto strong_self = weak_self.lock();
|
||
if (!strong_self) {
|
||
return;
|
||
}
|
||
if (sock_ptr != strong_self->getSock().get()) {
|
||
//已经重连socket,上次的socket的事件忽略掉
|
||
return;
|
||
}
|
||
strong_self->_timer.reset();
|
||
TraceL << strong_self->getIdentifier() << " on err: " << ex;
|
||
strong_self->onError(ex);
|
||
});
|
||
|
||
sock_ptr->setOnFlush([weak_self, sock_ptr]() {
|
||
auto strong_self = weak_self.lock();
|
||
if (!strong_self) {
|
||
return false;
|
||
}
|
||
if (sock_ptr != strong_self->getSock().get()) {
|
||
//已经重连socket,上传socket的事件忽略掉
|
||
return false;
|
||
}
|
||
strong_self->onFlush();
|
||
return true;
|
||
});
|
||
|
||
sock_ptr->setOnRead([weak_self, sock_ptr](const Buffer::Ptr &pBuf, struct sockaddr * addr, int addr_len) {
|
||
auto strong_self = weak_self.lock();
|
||
if (!strong_self) {
|
||
return;
|
||
}
|
||
if (sock_ptr != strong_self->getSock().get()) {
|
||
//已经重连socket,上传socket的事件忽略掉
|
||
return;
|
||
}
|
||
try {
|
||
strong_self->onRecvFrom(pBuf, addr, addr_len);
|
||
} catch (std::exception &ex) {
|
||
strong_self->shutdown(SockException(Err_other, ex.what()));
|
||
}
|
||
});
|
||
|
||
bool ret = getSock()->bindUdpSock(local_port, _net_adapter);
|
||
if (!ret) {
|
||
WarnL << "UDP output bind local error";
|
||
}
|
||
auto peer_addr = SockUtil::make_sockaddr(peer_host.c_str(), peer_port);
|
||
|
||
//只能软绑定
|
||
ret = getSock()->bindPeerAddr((struct sockaddr *)&peer_addr, 0, true);
|
||
if (!ret) {
|
||
WarnL << "UDP output bind peer error";
|
||
}
|
||
// TraceL << getIdentifier() << " start connect " << url << ":" << peer_port;
|
||
}
|
||
|
||
void UdpClient::shutdown(const SockException &ex) {
|
||
_timer.reset();
|
||
SocketHelper::shutdown(ex);
|
||
}
|
||
|
||
bool UdpClient::alive() const {
|
||
if (_timer) {
|
||
//连接中或已连接
|
||
return true;
|
||
}
|
||
//在websocket client(zlmediakit)相关代码中,
|
||
//_timer一直为空,但是socket fd有效,alive状态也应该返回true
|
||
auto sock = getSock();
|
||
return sock && sock->alive();
|
||
}
|
||
|
||
void UdpClient::setNetAdapter(const string &local_ip) {
|
||
_net_adapter = local_ip;
|
||
}
|
||
|
||
std::string UdpClient::getIdentifier() const {
|
||
if (_id.empty()) {
|
||
static atomic<uint64_t> s_index { 0 };
|
||
_id = toolkit::demangle(typeid(*this).name()) + "-" + to_string(++s_index);
|
||
}
|
||
return _id;
|
||
}
|
||
|
||
} /* namespace toolkit */
|