195 lines
5.6 KiB
C++
195 lines
5.6 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.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#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 */
|