#ifndef TCPSOCKETCLIENT_H
#define TCPSOCKETCLIENT_H
#include <iostream>
#include <memory>
#include <functional>
namespace common
{
typedef std::function<void(const std::string& message)> MessageReceivedCallback;
typedef std::function<void(bool isConnected)> ConnectionStatusCallback;
class TcpSocketClient
{
public:
TcpSocketClient(const std::string& serverIp, int serverPort);
~TcpSocketClient();
public:
bool connect();
bool isConnect();
void close();
bool send(const std::string& data);
std::string receive();
void startListening();
void stopListening();
void reconnect();
void setIsReconnect(bool bIsReconnect);
void setReceivedCallback(MessageReceivedCallback callback);
void setConnectionStatusCallback(ConnectionStatusCallback callback);
private:
class Impl;
std::shared_ptr<Impl> m_pImpl;
};
}
#endif // TCPSOCKETCLIENT_H
以下是实现文件
#include "tcpsocketclient.h"
#include <string>
#include <cstring>
#include <cstdlib>
#include <thread>
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
using namespace common;
#define RECV_BUFF_SIZE 1024
class TcpSocketClient::Impl
{
public:
Impl(const std::string& serverIp, int serverPort)
: serverIp_(serverIp)
, serverPort_(serverPort)
{
}
~Impl()
{
close();
}
bool connect()
{
// 创建套接字
socket_ = ::socket(AF_INET, SOCK_STREAM, 0);
if (socket_ == -1)
{
std::cerr << "Error creating socket." << std::endl;
return false;
}
// 设置服务器地址
serverAddr_.sin_family = AF_INET;
serverAddr_.sin_port = htons(serverPort_);
serverAddr_.sin_addr.s_addr = inet_addr(serverIp_.c_str());
// 连接到服务器
if (::connect(socket_, (struct sockaddr*)&serverAddr_, sizeof(serverAddr_)) == -1)
{
std::cerr << "Error connecting to server." << std::endl;
return false;
}
// 状态返回
if (connectionStatusCallback_)
{
connectionStatusCallback_(true);
}
return true;
}
bool isConnect()
{
return socket_ != -1;
}
void close()
{
if (socket_ != -1)
{
#ifdef _WIN32
closesocket(socket_);
#else
close(socket_);
#endif
socket_ = -1;
}
}
bool send(const std::string& data)
{
if (socket_ == -1)
{
std::cerr << "Not connected to the server." << std::endl;
return false;
}
int bytesSent = ::send(socket_, data.c_str(), data.length(), 0);
if (bytesSent == -1)
{
std::cerr << "Error sending data." << std::endl;
return false;
}
return true;
}
std::string receive()
{
if (socket_ == -1)
{
std::cerr << "Not connected to the server." << std::endl;
return "";
}
char buffer[RECV_BUFF_SIZE];
int bytesRead = recv(socket_, buffer, RECV_BUFF_SIZE, 0);
if (bytesRead == -1)
{
std::cerr << "Error receiving data." << std::endl;
return "";
}
return std::string(buffer, bytesRead);
}
void startListening()
{
listeningThread_ = std::thread([this]()
{
while (true)
{
std::string response = receive();
if (!response.empty())
{
std::cout << "Received: " << response << std::endl;
if (messageReceivedCallback_)
{
messageReceivedCallback_(response);
}
}
else
{
if (connectionStatusCallback_)
{
connectionStatusCallback_(false);
}
if (isReconnect_)
{
reconnect();
}
}
}
});
}
void stopListening()
{
if (listeningThread_.joinable())
{
listeningThread_.join();
}
}
void reconnect()
{
while (true)
{
if (connect())
{
std::cout << "Reconnected to the server." << std::endl;
break;
}
std::cout << "Failed to reconnect. Retrying in 5 seconds..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
}
}
void setIsReconnect(bool bIsReconnect)
{
isReconnect_ = bIsReconnect;
}
void setReceivedCallback(MessageReceivedCallback callback)
{
messageReceivedCallback_ = callback;
}
void setConnectionStatusCallback(ConnectionStatusCallback callback)
{
connectionStatusCallback_ = callback;
}
private:
std::string serverIp_;
int serverPort_;
int socket_{ -1 };
bool isReconnect_{ true };
struct sockaddr_in serverAddr_;
std::thread listeningThread_;
MessageReceivedCallback messageReceivedCallback_;
ConnectionStatusCallback connectionStatusCallback_;
};
TcpSocketClient::TcpSocketClient(const std::string& serverIp, int serverPort)
:m_pImpl(std::make_shared<TcpSocketClient::Impl>(serverIp, serverPort))
{
}
TcpSocketClient::~TcpSocketClient()
{
m_pImpl->close();
}
bool TcpSocketClient::connect()
{
return m_pImpl->connect();
}
bool TcpSocketClient::isConnect()
{
return m_pImpl->isConnect();
}
void TcpSocketClient::close()
{
return m_pImpl->close();
}
bool TcpSocketClient::send(const std::string& data)
{
return m_pImpl->send(data);
}
std::string TcpSocketClient::receive()
{
return m_pImpl->receive();
}
void TcpSocketClient::startListening()
{
return m_pImpl->startListening();
}
void TcpSocketClient::stopListening()
{
return m_pImpl->stopListening();
}
void TcpSocketClient::reconnect()
{
return m_pImpl->reconnect();
}
void TcpSocketClient::setIsReconnect(bool bIsReconnect)
{
return m_pImpl->setIsReconnect(bIsReconnect);
}
void TcpSocketClient::setReceivedCallback(MessageReceivedCallback callback)
{
return m_pImpl->setReceivedCallback(callback);
}
void TcpSocketClient::setConnectionStatusCallback(ConnectionStatusCallback callback)
{
return m_pImpl->setConnectionStatusCallback(callback);
}