#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <vector>
#include <map>
#include <string>
#include <ctime>
#include<algorithm>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define HEARTBEATTIME 1000
class TcpServer {
public:
TcpServer();
~TcpServer();
bool start(int port);
void stop();
int sendData(SOCKET clientSocket, const char* data, int dataLength);
void handle();
static DWORD WINAPI ThreadAccept(LPVOID lpParam);
static DWORD WINAPI ThreadRecvData(LPVOID lpParam);
static DWORD WINAPI ThreadHeartBeat(LPVOID lpParam);
public:
std::vector<SOCKET> socketsToRemove;
BOOL m_bExit;
BOOL m_bHeartBeat;
int heartbeatInterval;
private:
SOCKET listenSocket;
std::vector<SOCKET> clientSockets;
std::map<SOCKET, std::time_t> clientLastHeartbeatTime;
bool setSocketNonBlocking(SOCKET socket);
void acceptNewClients();
void receiveClientData();
void sendHeartbeatsAndCheck();
void removeDisconnectedClients(std::vector<SOCKET>& socketsToRemove);
};
TcpServer::TcpServer() : listenSocket(INVALID_SOCKET),
heartbeatInterval(5), m_bExit(false), m_bHeartBeat(false)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
int result = WSAStartup(wVersionRequested, &wsaData);
if (result!= 0)
{
std::cerr << "WSAStartup failed: " << result << std::endl;
}
}
TcpServer::~TcpServer()
{
stop();
WSACleanup();
}
bool TcpServer::start(int port)
{
listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
std::cerr << "Socket creation failed: " << WSAGetLastError() << std::endl;
return false;
}
if (!setSocketNonBlocking(listenSocket))
{
std::cerr << "Failed to set listen socket non-blocking" << std::endl;
closesocket(listenSocket);
return false;
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(port);
int result = bind(listenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
if (result == SOCKET_ERROR)
{
std::cerr << "Bind failed: " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
return false;
}
result = listen(listenSocket, SOMAXCONN);
if (result == SOCKET_ERROR)
{
std::cerr << "Listen failed: " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
return false;
}
return true;
}
void TcpServer::stop()
{
if (listenSocket!= INVALID_SOCKET)
{
closesocket(listenSocket);
listenSocket = INVALID_SOCKET;
}
for(int i=0;i<clientSockets.size();++i)
{
closesocket(clientSockets[i]);
}
clientSockets.clear();
clientLastHeartbeatTime.clear();
}
bool TcpServer::setSocketNonBlocking(SOCKET socket)
{
u_long iMode = 1;
int result = ioctlsocket(socket, FIONBIO, &iMode);
if (result == SOCKET_ERROR)
{
std::cerr << "ioctlsocket failed: " << WSAGetLastError() << std::endl;
return false;
}
return true;
}
int TcpServer::sendData(SOCKET clientSocket, const char* data, int dataLength)
{
if (clientSocket == INVALID_SOCKET)
{
std::cerr << "Invalid client socket, cannot send data" << std::endl;
return SOCKET_ERROR;
}
int totalBytesSent = 0;
while (totalBytesSent < dataLength)
{
int bytesSent = ::send(clientSocket, data + totalBytesSent, dataLength - totalBytesSent, 0);
if (bytesSent == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
continue;
}
return SOCKET_ERROR;
}
totalBytesSent += bytesSent;
}
return totalBytesSent;
}
void TcpServer::acceptNewClients()
{
SOCKET newClientSocket = accept(listenSocket, NULL, NULL);
if (newClientSocket == INVALID_SOCKET)
{
if (WSAGetLastError()!= WSAEWOULDBLOCK)
{
std::cerr << "Accept failed: " << WSAGetLastError() << std::endl;
}
return;
}
else
{
std::cout << "Accept success: " << newClientSocket << std::endl;
}
if (!setSocketNonBlocking(newClientSocket))
{
std::cerr << "Failed to set client socket non-blocking" << std::endl;
closesocket(newClientSocket);
return;
}
clientSockets.push_back(newClientSocket);
clientLastHeartbeatTime[newClientSocket] = std::time(NULL);
}
void TcpServer::receiveClientData()
{
for (size_t i = 0; i < clientSockets.size(); ++i)
{
SOCKET clientSocket = clientSockets[i];
char buffer[1024];
int bytesReceived = ::recv(clientSocket, buffer, sizeof(buffer), 0);
if (bytesReceived == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
continue;
}
}
else
{
buffer[bytesReceived] = '\0';
std::string receivedData(buffer);
std::cout << "Received from client " << clientSocket << ": " << receivedData << std::endl;
clientLastHeartbeatTime[clientSocket] = std::time(NULL);
std::string heartbeatData = buffer;
heartbeatData += " recvok:";
int sentBytes = sendData(clientSocket, heartbeatData.c_str(), heartbeatData.length());
}
}
}
void TcpServer::sendHeartbeatsAndCheck()
{
const char* heartbeatData = "HEARTBEAT";
int dataLength = strlen(heartbeatData);
for (std::map<SOCKET, std::time_t>::iterator it = clientLastHeartbeatTime.begin(); it!= clientLastHeartbeatTime.end(); ++it)
{
SOCKET clientSocket = it->first;
std::time_t& lastHeartbeatTime = it->second;
std::time_t currentTime = std::time(NULL);
if (currentTime - lastHeartbeatTime > heartbeatInterval)
{
socketsToRemove.push_back(clientSocket);
continue;
}
int sentBytes = sendData(clientSocket, heartbeatData, dataLength);
if (sentBytes == SOCKET_ERROR)
{
socketsToRemove.push_back(clientSocket);
continue;
}
}
}
void TcpServer::removeDisconnectedClients(std::vector<SOCKET>& socketsToRemove)
{
for (std::vector<SOCKET>::iterator it = socketsToRemove.begin(); it!= socketsToRemove.end(); ++it)
{
SOCKET socketToRemove = *it;
vector<SOCKET>::iterator clientIt = find(clientSockets.begin(), clientSockets.end(), socketToRemove);
if (clientIt!= clientSockets.end())
{
cout << "Remove :" << *clientIt << endl;
clientSockets.erase(clientIt);
clientLastHeartbeatTime.erase(socketToRemove);
}
}
}
DWORD WINAPI TcpServer::ThreadAccept(LPVOID lpParam)
{
TcpServer* t_Server = static_cast<TcpServer*>(lpParam);
while (t_Server->m_bExit == false)
{
t_Server->acceptNewClients();
}
return 0;
}
DWORD WINAPI TcpServer::ThreadRecvData(LPVOID lpParam)
{
TcpServer* t_Server = static_cast<TcpServer*>(lpParam);
while (t_Server->m_bExit == false)
{
t_Server->receiveClientData();
}
return 0;
}
DWORD WINAPI TcpServer::ThreadHeartBeat(LPVOID lpParam)
{
TcpServer* t_Server = static_cast<TcpServer*>(lpParam);
while (t_Server->m_bExit == false)
{
Sleep(HEARTBEATTIME);
t_Server->sendHeartbeatsAndCheck();
if (t_Server->heartbeatInterval > 0)
{
t_Server->removeDisconnectedClients(t_Server->socketsToRemove);
}
}
return 0;
}
void TcpServer::handle()
{
HANDLE acceptThreadHandle = CreateThread(NULL, 0, ThreadAccept, this, 0, NULL);
if (acceptThreadHandle == NULL)
{
std::cerr << "Create accept thread failed: " << GetLastError() << std::endl;
}
else
{
std::cerr << "Create accept thread success: " << acceptThreadHandle << std::endl;
}
HANDLE recvDatatThreadHandle = CreateThread(NULL, 0, ThreadRecvData, this, 0, NULL);
if (acceptThreadHandle == NULL)
{
std::cerr << "Create recvData thread failed: " << GetLastError() << std::endl;
}
else
{
std::cerr << "Create recvData thread success: " << recvDatatThreadHandle << std::endl;
}
if (m_bHeartBeat == true)
{
HANDLE heartBeatThreadHandle = CreateThread(NULL, 0, ThreadHeartBeat, this, 0, NULL);
if (acceptThreadHandle == NULL)
{
std::cerr << "Create heartBeat thread failed: " << GetLastError() << std::endl;
}
else
{
std::cerr << "Create heartBeat thread success: " << heartBeatThreadHandle << std::endl;
}
}
}
int main()
{
TcpServer server;
server.heartbeatInterval = 30;
server.m_bHeartBeat = true;
if (server.start(6000))
{
while (true)
{
server.handle();
Sleep(100);
break;
}
}
else
{
std::cout << "server initiatefail" << std::endl;
}
Sleep(1000000);
return 0;
}
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <string>
#include <process.h>
#include<list>
#include<vector>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 6000
#define RECV_BUF_SIZE 1024
#define HEARTBEAT_INTERVAL 5000
#define HEARTBEAT_TIMEOUT 10000
#define MAX_RECONNECT_ATTEMPTS 10
#define RECONNECT_INTERVAL_SECONDS 2
class TCPClient
{
public:
TCPClient();
~TCPClient();
bool connectToServer();
void disconnect();
int sendData(const std::string& data);
private:
SOCKET m_socket;
sockaddr_in m_serverAddr;
bool m_connected;
DWORD m_lastHeartbeatTime;
bool m_heartbeatSent;
HANDLE m_heartbeatThreadHandle;
bool m_heartbeatThreadRunning;
static unsigned int __stdcall HeartbeatThread(void* param);
bool sendHeartbeat();
bool checkHeartbeatResponse();
bool setSocketNonBlocking();
bool reconnect();
bool initializeWinsock();
void closeSocket();
static unsigned int __stdcall ReceiveDataThread(void* param);
HANDLE m_receiveThreadHandle;
bool m_receiveThreadRunning;
};
TCPClient::TCPClient() : m_socket(INVALID_SOCKET), m_connected(false),
m_lastHeartbeatTime(0), m_heartbeatSent(false),
m_heartbeatThreadHandle(NULL), m_heartbeatThreadRunning(false),
m_receiveThreadHandle(NULL), m_receiveThreadRunning(false)
{
if (!initializeWinsock())
{
std::cerr << "初始化Winsock库失败" << std::endl;
}
m_serverAddr.sin_family = AF_INET;
m_serverAddr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &(m_serverAddr.sin_addr)) <= 0)
{
std::cerr << "inet_pton转换IP地址错误" << std::endl;
}
}
TCPClient::~TCPClient()
{
disconnect();
if (m_heartbeatThreadHandle!= NULL)
{
m_heartbeatThreadRunning = false;
WaitForSingleObject(m_heartbeatThreadHandle, INFINITE);
CloseHandle(m_heartbeatThreadHandle);
}
if (m_receiveThreadHandle!= NULL)
{
m_receiveThreadRunning = false;
WaitForSingleObject(m_receiveThreadHandle, INFINITE);
CloseHandle(m_receiveThreadHandle);
}
WSACleanup();
}
bool TCPClient::connectToServer()
{
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET)
{
std::cerr << "创建套接字失败,错误码: " << WSAGetLastError() << std::endl;
return false;
}
if (!setSocketNonBlocking())
{
std::cerr << "设置套接字为非阻塞模式失败" << std::endl;
closeSocket();
return false;
}
int ret = connect(m_socket, (struct sockaddr*)&m_serverAddr, sizeof(m_serverAddr));
if (ret == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode!= WSAEWOULDBLOCK)
{
std::cerr << "连接服务器失败,错误码: " << errCode << std::endl;
closeSocket();
return false;
}
}
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(m_socket, &writefds);
ret = select(0, NULL, &writefds, NULL, &timeout);
if (ret == SOCKET_ERROR)
{
std::cerr << "select函数出错,错误码: " << WSAGetLastError() << std::endl;
closeSocket();
return false;
}
else if (ret == 0)
{
std::cerr << "连接超时" << std::endl;
closeSocket();
return false;
}
if (FD_ISSET(m_socket, &writefds))
{
m_connected = true;
m_receiveThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ReceiveDataThread, this, 0, NULL);
if (m_receiveThreadHandle == NULL)
{
std::cerr << "创建接收数据线程失败" << std::endl;
closeSocket();
return false;
}
m_receiveThreadRunning = true;
m_heartbeatThreadHandle = (HANDLE)_beginthreadex(NULL, 0, HeartbeatThread, this, 0, NULL);
if (m_heartbeatThreadHandle == NULL)
{
std::cerr << "创建心跳包线程失败" << std::endl;
closeSocket();
return false;
}
m_heartbeatThreadRunning = true;
std::cout << "成功连接到服务器" << std::endl;
return true;
}
return false;
}
void TCPClient::disconnect()
{
if (m_connected)
{
closesocket(m_socket);
m_connected = false;
std::cout << "已断开与服务器的连接" << std::endl;
}
m_receiveThreadRunning = false;
m_heartbeatThreadRunning = false;
}
int TCPClient::sendData(const std::string& data)
{
if (!m_connected)
{
if (reconnect())
{
}
else
{
std::cerr << "未连接到服务器,无法发送数据" << std::endl;
return SOCKET_ERROR;
}
}
int ret = send(m_socket, data.c_str(), data.size(), 0);
if (ret == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK)
{
return 0;
}
else
{
std::cerr << "发送数据失败,错误码: " << errCode << std::endl;
if (errCode == WSAECONNRESET || errCode == WSAENETRESET)
{
if (reconnect())
{
return sendData(data);
}
}
return SOCKET_ERROR;
}
}
return ret;
}
bool TCPClient::sendHeartbeat()
{
if (!m_connected)
{
return false;
}
const std::string heartbeatData = "HEARTBEAT_CLIENT";
int ret = send(m_socket, heartbeatData.c_str(), heartbeatData.size(), 0);
if (ret == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK)
{
return false;
}
else
{
std::cerr << "发送心跳包失败,错误码: " << errCode << std::endl;
return false;
}
}
m_heartbeatSent = true;
return true;
}
bool TCPClient::checkHeartbeatResponse()
{
if (!m_connected)
{
return false;
}
char buffer[RECV_BUF_SIZE];
int ret = recv(m_socket, buffer, RECV_BUF_SIZE, 0);
if (ret == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK)
{
return false;
}
else
{
std::cerr << "接收心跳包响应失败,错误码: " << errCode << std::endl;
return false;
}
}
else if (ret == 0)
{
std::cerr << "服务器关闭了连接" << std::endl;
disconnect();
return false;
}
else
{
std::string response(buffer, ret);
if (response == "HEARTBEAT_ACK")
{
return true;
}
}
return false;
}
bool TCPClient::setSocketNonBlocking()
{
u_long mode = 1;
int ret = ioctlsocket(m_socket, FIONBIO, &mode);
return ret!= SOCKET_ERROR;
}
bool TCPClient::reconnect()
{
int attempt = 0;
while (attempt < MAX_RECONNECT_ATTEMPTS)
{
attempt++;
closeSocket();
Sleep(RECONNECT_INTERVAL_SECONDS * 1000);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET)
{
std::cerr << "重连时创建套接字失败,错误码: " << WSAGetLastError() << std::endl;
continue;
}
if (!setSocketNonBlocking())
{
std::cerr << "重连时设置套接字为非阻塞模式失败" << std::endl;
closeSocket();
continue;
}
int ret = connect(m_socket, (struct sockaddr*)&m_serverAddr, sizeof(m_serverAddr));
if (ret == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode!= WSAEWOULDBLOCK)
{
std::cerr << "重连失败,错误码: " << errCode << std::endl;
continue;
}
}
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(m_socket, &writefds);
ret = select(0, NULL, &writefds, NULL, &timeout);
if (ret == SOCKET_ERROR)
{
std::cerr << "重连时select函数出错,错误码: " << WSAGetLastError() << std::endl;
closeSocket();
continue;
}
else if (ret == 0)
{
std::cerr << "重连超时" << std::endl;
closeSocket();
continue;
}
if (FD_ISSET(m_socket, &writefds))
{
m_connected = true;
if (m_receiveThreadHandle!= NULL)
{
m_receiveThreadRunning = false;
WaitForSingleObject(m_receiveThreadHandle, INFINITE);
CloseHandle(m_receiveThreadHandle);
}
m_receiveThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ReceiveDataThread, this, 0, NULL);
if (m_receiveThreadHandle == NULL)
{
std::cerr << "重连后创建接收数据线程失败" << std::endl;
closeSocket();
return false;
}
m_receiveThreadRunning = true;
if (m_heartbeatThreadHandle!= NULL)
{
m_heartbeatThreadRunning = false;
WaitForSingleObject(m_heartbeatThreadHandle, INFINITE);
CloseHandle(m_heartbeatThreadHandle);
}
m_heartbeatThreadHandle = (HANDLE)_beginthreadex(NULL, 0, HeartbeatThread, this, 0, NULL);
if (m_heartbeatThreadHandle == NULL)
{
std::cerr << "重连后创建心跳包线程失败" << std::endl;
closeSocket();
return false;
}
m_heartbeatThreadRunning = true;
std::cout << "重连成功" << std::endl;
return true;
}
}
std::cerr << "达到最大重连尝试次数,重连失败" << std::endl;
return false;
}
bool TCPClient::initializeWinsock()
{
WSADATA wsaData;
return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
}
void TCPClient::closeSocket()
{
if (m_socket!= INVALID_SOCKET)
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
}
unsigned int __stdcall TCPClient::HeartbeatThread(void* param)
{
TCPClient* client = static_cast<TCPClient*>(param);
while (client->m_heartbeatThreadRunning && client->m_connected)
{
DWORD currentTime = GetTickCount();
if (currentTime - client->m_lastHeartbeatTime >= HEARTBEAT_INTERVAL)
{
if (client->sendHeartbeat())
{
client->m_lastHeartbeatTime = currentTime;
}
}
if (currentTime - client->m_lastHeartbeatTime > HEARTBEAT_TIMEOUT)
{
std::cerr << "心跳包超时,通知主线程尝试重连" << std::endl;
client->m_connected = false;
break;
}
Sleep(100);
}
return 0;
}
unsigned int __stdcall TCPClient::ReceiveDataThread(void* param)
{
TCPClient* client = static_cast<TCPClient*>(param);
std::string receivedData;
while (client->m_receiveThreadRunning && client->m_connected)
{
char recvBuf[RECV_BUF_SIZE];
int ret = recv(client->m_socket, recvBuf, RECV_BUF_SIZE, 0);
if (ret == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK)
{
continue;
}
else
{
std::cerr << "接收数据线程中接收数据失败,错误码: " << errCode << std::endl;
if (errCode == WSAECONNRESET || errCode == WSAENETRESET)
{
client->m_connected = false;
break;
}
}
}
else if (ret == 0)
{
std::cerr << "服务器关闭了连接(接收数据线程中)" << std::endl;
client->m_connected = false;
break;
}
else
{
receivedData.assign(recvBuf, ret);
std::cout << "接收数据线程从服务器接收到数据: " << receivedData << std::endl;
}
}
return 0;
}
int main()
{
TCPClient client;
if (client.connectToServer())
{
while (true)
{
std::string sendDataStr = "Hello, server!\n";
client.sendData(sendDataStr);
Sleep(100);
}
}
return 0;
}