2021-10-09 00:14:49 +08:00
|
|
|
//
|
|
|
|
// Created by 29019 on 2020/4/18.
|
|
|
|
//
|
|
|
|
#define _WSPIAPI_H_
|
|
|
|
#define _WINSOCKAPI_
|
|
|
|
#include "tcp_client.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <cstring>
|
|
|
|
#include <string.h>
|
2021-10-12 00:51:48 +08:00
|
|
|
#include <chrono>
|
|
|
|
|
|
|
|
using namespace std::chrono;
|
2021-10-09 00:14:49 +08:00
|
|
|
|
|
|
|
static void conn_writecb(struct bufferevent *, void *);
|
|
|
|
static void conn_readcb(struct bufferevent *, void *);
|
|
|
|
static void conn_eventcb(struct bufferevent *, short, void *);
|
|
|
|
|
|
|
|
void delay(int ms);
|
|
|
|
int ThreadRun(TcpClientLibevent *p);
|
|
|
|
|
|
|
|
void conn_writecb(struct bufferevent *bev, void *user_data)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 运行线程
|
|
|
|
int ThreadRun(TcpClientLibevent *p) {
|
|
|
|
if (nullptr != p) {
|
|
|
|
int ret = p->Dispatch();
|
|
|
|
if (0 > ret){
|
|
|
|
}
|
2021-10-12 00:51:48 +08:00
|
|
|
while ((p->mStatus != TcpClientLibevent::STOP))
|
2021-10-09 00:14:49 +08:00
|
|
|
{
|
2021-10-12 00:51:48 +08:00
|
|
|
if ((p->mStatus == TcpClientLibevent::FAIL) ||
|
|
|
|
(p->mStatus == TcpClientLibevent::UNCONNECTED)){ //连接失败,如果有设置自动重连就一直重连
|
2021-10-09 00:14:49 +08:00
|
|
|
p->ConnectServer();
|
|
|
|
#ifdef _WIN32
|
|
|
|
Sleep(100);
|
|
|
|
#else
|
|
|
|
//todo linux版本sleep
|
|
|
|
#endif
|
2022-01-31 01:00:02 +08:00
|
|
|
}else {
|
|
|
|
ret = p->Dispatch();
|
2021-10-09 00:14:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void conn_readcb(struct bufferevent *bev, void *user_data)
|
|
|
|
{
|
|
|
|
TcpClientLibevent *server = (TcpClientLibevent*)user_data;
|
|
|
|
struct evbuffer *input = bufferevent_get_input(bev);
|
|
|
|
size_t sz = evbuffer_get_length(input);
|
|
|
|
if (sz > 0)
|
|
|
|
{
|
2022-01-31 01:00:02 +08:00
|
|
|
uint8_t *msg = new uint8_t[sz + 1];
|
2021-10-09 00:14:49 +08:00
|
|
|
int ret = bufferevent_read(bev, msg, sz);
|
|
|
|
printf("%s\n", msg);
|
2022-01-31 01:00:02 +08:00
|
|
|
msg[sz] = '\0';
|
2021-10-09 00:14:49 +08:00
|
|
|
if(server->mObserver != nullptr){
|
2021-11-24 00:37:05 +08:00
|
|
|
server->mObserver->OnData(msg, ret);
|
2021-10-09 00:14:49 +08:00
|
|
|
}
|
|
|
|
delete[] msg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void conn_eventcb(struct bufferevent *bev, short events, void *user_data)
|
|
|
|
{
|
|
|
|
TcpClientLibevent *p;
|
|
|
|
p = (TcpClientLibevent *)user_data;
|
2021-10-11 00:00:10 +08:00
|
|
|
if (p == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
2021-10-09 00:14:49 +08:00
|
|
|
if (events & BEV_EVENT_EOF) {
|
|
|
|
if (nullptr != p->mObserver)
|
2021-11-22 23:53:21 +08:00
|
|
|
p->mObserver->OnDisConnected("服务器主动断开连接");
|
2021-10-09 00:14:49 +08:00
|
|
|
if (p != nullptr)
|
2022-02-18 00:18:28 +08:00
|
|
|
if (p->mStatus != TcpClientLibevent::STOP)
|
|
|
|
p->mStatus = TcpClientLibevent::UNCONNECTED;
|
2021-10-09 00:14:49 +08:00
|
|
|
printf("Connection closed\n");
|
|
|
|
}
|
|
|
|
else if (events & BEV_EVENT_ERROR) {
|
|
|
|
printf("Got an error on the connection: %s\n", strerror(errno));
|
2022-02-18 00:18:28 +08:00
|
|
|
if (nullptr != p) {
|
|
|
|
if (nullptr != p->mObserver)
|
|
|
|
p->mObserver->OnDisConnected("连接失败");
|
|
|
|
if(p->mStatus != TcpClientLibevent::STOP)
|
|
|
|
p->mStatus = TcpClientLibevent::FAIL;
|
|
|
|
}
|
2021-10-11 00:00:10 +08:00
|
|
|
}
|
2021-10-09 00:14:49 +08:00
|
|
|
else if (events & BEV_EVENT_CONNECTED) {
|
2021-10-11 00:00:10 +08:00
|
|
|
p->mSocketFD = (uint64_t)event_get_fd(&(bev->ev_read));
|
2021-10-09 00:14:49 +08:00
|
|
|
//客户端链接成功后,给服务器发送第一条消息
|
2022-01-09 11:00:38 +08:00
|
|
|
std::cout << "socket fd" << p->mSocketFD;
|
2021-10-09 00:14:49 +08:00
|
|
|
if (nullptr != p->mObserver)
|
|
|
|
p->mObserver->OnConnected();
|
2021-10-12 00:51:48 +08:00
|
|
|
p->mStatus = TcpClientLibevent::CONNECTED;
|
2021-10-09 00:14:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
bufferevent_free(bev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void delay(int ms)
|
|
|
|
{
|
|
|
|
clock_t start = clock();
|
|
|
|
while (clock() - start < ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TcpClientLibevent::Connected() {
|
|
|
|
return (((mStatus != UNCONNECTED)&& (mStatus != FAIL) )?true : false);
|
|
|
|
}
|
|
|
|
|
2022-02-18 00:18:28 +08:00
|
|
|
|
2021-10-09 00:14:49 +08:00
|
|
|
TcpClientLibevent::TcpClientLibevent(std::string addrinfo, int port, TcpClientLibevent::TcpClientObserver *p) :
|
2021-10-12 00:51:48 +08:00
|
|
|
mStatus(UNCONNECTED),
|
|
|
|
mObserver(nullptr)
|
2021-10-09 00:14:49 +08:00
|
|
|
{
|
2021-12-30 16:56:16 +08:00
|
|
|
memset(&mSrv, 0, sizeof(mSrv));
|
2021-10-09 00:14:49 +08:00
|
|
|
#ifdef linux
|
|
|
|
mSrv.sin_addr.s_addr = inet_addr(addrinfo.c_str());
|
|
|
|
mSrv.sin_family = AF_INET;
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
2021-12-30 16:56:16 +08:00
|
|
|
mSrv.sin_addr.S_un.S_addr = inet_addr(addrinfo.c_str());
|
|
|
|
mSrv.sin_family = AF_INET;
|
2021-10-09 00:14:49 +08:00
|
|
|
#endif
|
2021-12-30 16:56:16 +08:00
|
|
|
mSrv.sin_port = htons(port);
|
|
|
|
mBase = event_base_new();
|
|
|
|
if (!mBase)
|
|
|
|
{
|
|
|
|
printf("Could not initialize libevent\n");
|
|
|
|
}
|
2021-10-09 00:14:49 +08:00
|
|
|
|
|
|
|
#ifdef WIN32
|
2021-12-30 16:56:16 +08:00
|
|
|
evthread_use_windows_threads();
|
2021-10-09 00:14:49 +08:00
|
|
|
#else
|
2021-12-30 16:56:16 +08:00
|
|
|
evthread_use_pthreads();
|
2021-10-09 00:14:49 +08:00
|
|
|
#endif
|
2021-12-30 16:56:16 +08:00
|
|
|
this->mThread = new thread(ThreadRun, this);
|
|
|
|
this->mObserver = p;
|
|
|
|
mByteRecv = 0;
|
|
|
|
mByteSend = 0;
|
2021-10-09 00:14:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int TcpClientLibevent::ConnectServer() {
|
2021-10-11 00:00:10 +08:00
|
|
|
printf("server conecting...\r\n");
|
2021-10-09 00:14:49 +08:00
|
|
|
evthread_make_base_notifiable(mBase);
|
2022-02-18 00:18:28 +08:00
|
|
|
mMux.lock();
|
|
|
|
|
2021-10-12 00:51:48 +08:00
|
|
|
mBev = bufferevent_socket_new(mBase, -1,
|
2021-10-09 00:14:49 +08:00
|
|
|
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
|
2021-10-12 00:51:48 +08:00
|
|
|
if (nullptr == mBev) {
|
2021-10-09 00:14:49 +08:00
|
|
|
this->mStatus = TcpClientLibevent::FAIL;
|
2022-02-18 00:18:28 +08:00
|
|
|
|
2021-10-09 00:14:49 +08:00
|
|
|
return - 1;
|
|
|
|
}
|
2021-10-12 00:51:48 +08:00
|
|
|
bufferevent_setcb(mBev, conn_readcb, conn_writecb, conn_eventcb, this);
|
|
|
|
int flag = bufferevent_socket_connect(mBev, (struct sockaddr *)&mSrv, sizeof(mSrv));
|
|
|
|
bufferevent_enable(mBev, EV_READ | EV_WRITE);
|
2021-10-09 00:14:49 +08:00
|
|
|
if (-1 == flag) {
|
|
|
|
this->mStatus = TcpClientLibevent::FAIL;
|
2022-02-18 00:18:28 +08:00
|
|
|
|
2021-10-12 00:51:48 +08:00
|
|
|
bufferevent_free(mBev);
|
|
|
|
mBev = nullptr;
|
2021-10-09 00:14:49 +08:00
|
|
|
printf("Connect failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2021-10-12 00:51:48 +08:00
|
|
|
this->mStatus = TcpClientLibevent::CONNECTING;
|
2022-02-18 00:18:28 +08:00
|
|
|
mMux.unlock();
|
2021-10-12 00:51:48 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TcpClientLibevent::ConnectServerSync()
|
|
|
|
{
|
2022-02-18 00:18:28 +08:00
|
|
|
mMux.lock();
|
2021-10-12 00:51:48 +08:00
|
|
|
evthread_make_base_notifiable(mBase);
|
|
|
|
if (nullptr != mBev)
|
|
|
|
{
|
|
|
|
delete mBev;
|
|
|
|
}
|
|
|
|
mBev = bufferevent_socket_new(mBase, -1,
|
|
|
|
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
|
|
|
|
if (nullptr == mBev) {
|
|
|
|
this->mStatus = TcpClientLibevent::FAIL;
|
2022-02-18 00:18:28 +08:00
|
|
|
mMux.unlock();
|
2021-10-12 00:51:48 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
bufferevent_setcb(mBev, conn_readcb, conn_writecb, conn_eventcb, this);
|
|
|
|
int flag = bufferevent_socket_connect(mBev, (struct sockaddr*)&mSrv, sizeof(mSrv));
|
|
|
|
bufferevent_enable(mBev, EV_READ | EV_WRITE);
|
|
|
|
if (-1 == flag) {
|
|
|
|
this->mStatus = TcpClientLibevent::FAIL;
|
|
|
|
bufferevent_free(mBev);
|
|
|
|
mBev = nullptr;
|
|
|
|
printf("Connect failed\n");
|
2022-02-18 00:18:28 +08:00
|
|
|
mMux.unlock();
|
2021-10-12 00:51:48 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
this->mStatus = TcpClientLibevent::CONNECTING;
|
2022-02-18 00:18:28 +08:00
|
|
|
|
2021-10-12 00:51:48 +08:00
|
|
|
auto start = system_clock::to_time_t(system_clock::now());
|
|
|
|
while (this->mStatus != TcpClientLibevent::CONNECTED) {
|
|
|
|
auto end = system_clock::to_time_t(system_clock::now());
|
|
|
|
|
2021-11-22 23:53:21 +08:00
|
|
|
if ((end - start) > 5) {
|
2021-10-12 00:51:48 +08:00
|
|
|
this->mStatus = TcpClientLibevent::FAIL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-02-18 00:18:28 +08:00
|
|
|
mMux.unlock();
|
2021-10-09 00:14:49 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TcpClientLibevent::SetReconnect(bool reconn) {
|
|
|
|
this->mReConnect = reconn;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TcpClientLibevent::SetObserver(TcpClientLibevent::TcpClientObserver *ob) {
|
|
|
|
this->mObserver = ob;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TcpClientLibevent::Dispatch() {
|
|
|
|
return event_base_dispatch(mBase);;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TcpClientLibevent::Close() {
|
|
|
|
event_base_free(mBase);
|
|
|
|
return 0;
|
|
|
|
}
|
2021-10-11 00:00:10 +08:00
|
|
|
|
2021-11-22 23:53:21 +08:00
|
|
|
int TcpClientLibevent::SendDataAsync(const char* data, int len)
|
|
|
|
{
|
|
|
|
return bufferevent_write(this->mBev, data, len);
|
|
|
|
}
|
|
|
|
|
2021-10-11 00:00:10 +08:00
|
|
|
uint64_t TcpClientLibevent::SocketFd()
|
|
|
|
{
|
|
|
|
return mSocketFD;
|
|
|
|
}
|