stream-deploy/ZLM/3rdpart/ZLToolKit/src/Network/UdpClient.h

195 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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.
*/
#ifndef NETWORK_UDPCLIENT_H
#define NETWORK_UDPCLIENT_H
#include <memory>
#include "Socket.h"
#include "Util/SSLBox.h"
#include "Kcp.h"
namespace toolkit {
//Udp客户端Socket对象默认开始互斥锁
class UdpClient : public SocketHelper {
public:
using Ptr = std::shared_ptr<UdpClient>;
using OnRecvFrom = std::function<void(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len)>;
using OnErr = std::function<void(const SockException &)>;
UdpClient(const EventPoller::Ptr &poller = nullptr);
~UdpClient() override;
/**
* 开始连接udp服务器
* @param peer_host 服务器ip或域名
* @param peer_port 服务器端口
* @param local_port 本地端口
*/
virtual void startConnect(const std::string &peer_host, uint16_t peer_port, uint16_t local_port = 0);
/**
* 主动断开连接
* @param ex 触发onErr事件时的参数
*/
void shutdown(const SockException &ex = SockException(Err_shutdown, "self shutdown")) override;
/**
* 连接中或已连接返回true断开连接时返回false
*/
virtual bool alive() const;
/**
* 设置网卡适配器,使用该网卡与服务器通信
* @param local_ip 本地网卡ip
*/
virtual void setNetAdapter(const std::string &local_ip);
/**
* 唯一标识
*/
std::string getIdentifier() const override;
void setOnRecvFrom(OnRecvFrom cb) {
_on_recvfrom = std::move(cb);
}
void setOnError(OnErr cb) {
_on_err = std::move(cb);
}
protected:
virtual void onRecvFrom(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) {
if (_on_recvfrom) {
_on_recvfrom(buf, addr, addr_len);
}
}
void onRecv(const Buffer::Ptr &buf) override {}
void onError(const SockException &err) override {
DebugL;
if (_on_err) {
_on_err(err);
}
}
/**
* udp连接成功后每2秒触发一次该事件
*/
void onManager() override {}
private:
mutable std::string _id;
std::string _net_adapter = "::";
std::shared_ptr<Timer> _timer;
//对象个数统计
ObjectStatistic<UdpClient> _statistic;
OnRecvFrom _on_recvfrom;
OnErr _on_err;
};
//用于实现KCP客户端的模板对象
template<typename UdpClientType>
class UdpClientWithKcp : public UdpClientType {
public:
using Ptr = std::shared_ptr<UdpClientWithKcp>;
template<typename ...ArgsType>
UdpClientWithKcp(ArgsType &&...args)
:UdpClientType(std::forward<ArgsType>(args)...) {
_kcp_box = std::make_shared<KcpTransport>(false);
_kcp_box->setOnWrite([&](const Buffer::Ptr &buf) { public_send(buf); });
_kcp_box->setOnRead([&](const Buffer::Ptr &buf) { public_onRecv(buf); });
_kcp_box->setOnErr([&](const SockException &ex) { public_onErr(ex); });
}
~UdpClientWithKcp() override { }
void onRecvFrom(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) override {
//KCP 暂不支持一个UDP Socket 对多个目标,因此先忽略addr参数
_kcp_box->input(buf);
}
ssize_t send(Buffer::Ptr buf) override {
return _kcp_box->send(std::move(buf));
}
ssize_t sendto(Buffer::Ptr buf, struct sockaddr *addr = nullptr, socklen_t addr_len = 0) override {
//KCP 暂不支持一个UDP Socket 对多个目标,因此先忽略addr参数
return _kcp_box->send(std::move(buf));
}
inline void public_onRecv(const Buffer::Ptr &buf) {
//KCP 暂不支持一个UDP Socket 对多个目标,因此固定采用bind的地址参数
UdpClientType::onRecvFrom(buf, (struct sockaddr*)&_peer_addr, _peer_addr_len);
}
inline void public_send(const Buffer::Ptr &buf) {
UdpClientType::send(buf);
}
inline void public_onErr(const SockException &ex) { UdpClientWithKcp::onError(ex); }
virtual void startConnect(const std::string &peer_host, uint16_t peer_port, uint16_t local_port = 0) override {
_kcp_box->setPoller(UdpClientType::getPoller());
_peer_addr = SockUtil::make_sockaddr(peer_host.data(), peer_port);
_peer_addr_len = SockUtil::get_sock_len((const struct sockaddr*)&_peer_addr);
UdpClientType::startConnect(peer_host, peer_port, local_port);
}
void setMtu(int mtu) {
_kcp_box->setMtu(mtu);
}
void setInterval(int intervoal) {
_kcp_box->setInterval(intervoal);
}
void setRxMinrto(int rx_minrto) {
_kcp_box->setRxMinrto(rx_minrto);
}
void setWndSize(int sndwnd, int rcvwnd) {
_kcp_box->setWndSize(sndwnd, rcvwnd);
}
void setDelayMode(KcpTransport::DelayMode delay_mode) {
_kcp_box->setDelayMode(delay_mode);
}
void setFastResend(int resend) {
_kcp_box->setFastResend(resend);
}
void setFastackConserve(bool flag) {
_kcp_box->setFastackConserve(flag);
}
void setNoCwnd(bool flag) {
_kcp_box->setNoCwnd(flag);
}
void setStreamMode(bool flag) {
_kcp_box->setStreamMode(flag);
}
private:
struct sockaddr_storage _peer_addr;
int _peer_addr_len = 0;
KcpTransport::Ptr _kcp_box;
};
} /* namespace toolkit */
#endif /* NETWORK_UDPCLIENT_H */