TCPSocket.h
#include <winsock2.h>
/*_____________________________TCP-Client_______________________________*/
class TcpClinet
{
public:
TcpClinet();
TcpClinet(const std::string& IP, int Port);
~TcpClinet();
public:
bool Connect(bool bMutex = false) override;
void DisConnect(bool bMutex = false) override;
bool clearBuf_c();
bool recvBuf_c(char* pStr, int& len, int waitTimeMS = 0) override;
bool sendBuf_c(char const *pStr, const int& len) override;
protected:
bool Connect(std::string IP, int Port);
bool isActive();
private:
SOCKET m_socketClient;
};
/*__________________________TCP-Server__________________________________*/
class TcpServer
{
public:
TcpServer();
TcpServer(const std::string& IP, int Port);
~TcpServer();
public:
bool Connect(bool bMutex = false) override;
void DisConnect(bool bMutex = false) override;
bool clearBuf_c();
bool recvBuf_c(char* pStr, int& len, int waitTimeMS = 0) override;
bool sendBuf_c(char const *pStr, const int& len) override;
protected:
bool ConnectClient();
bool Connect(std::string IP, int Port);
private:
bool m_ServerOK;
SOCKET m_socketServer;
SOCKET m_socketClient;
std::list<SOCKET> m_socketClientList;
};
TCPSocket.cpp
/*_____________________________TCP-Client_______________________________*/
TcpClinet::TcpClinet(void)
{
m_socketClient = SOCKET_ERROR;
m_typeName = "TCP-客户端";
}
TcpClinet::TcpClinet(const std::string& IP, int Port)
: ISocketBaese(IP, Port, SOCKET_TYPE_TCP_CLINET)
{
m_socketClient = SOCKET_ERROR;
m_typeName = "TCP-客户端";
}
TcpClinet::~TcpClinet(void)
{
}
bool TcpClinet::Connect(bool bMutex)
{
if (bMutex)
{
QMutexLocker locker(&m_Mutex);
return Connect(m_IP, m_Port);
}
return Connect(m_IP, m_Port);
}
bool TcpClinet::Connect(std::string IP, int Port)
{
DisConnect();
char strIp[1024];
memset(strIp, '\0', 1024);
memcpy(strIp, IP.c_str(), IP.length());
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);//该函数的功能是加载一个Winsocket库版本
if (err != 0)
return false;
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
DisConnect();
return false;
}
m_socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socketClient == INVALID_SOCKET)
{
DisConnect();
return false;
}
/*
//设置发送/接收超时时间
struct timeval tSendTimeOut = { 6,0 }; //发送超时时间6s
struct timeval tRecvTimeOut = { 6,0 }; //接收超时时间6s
struct timeval tConnectTimeOut = { 0,500000 }; //连接超时时间500ms
if (SOCKET_ERROR == setsockopt(m_sclient, SOL_SOCKET, SO_SNDTIMEO, (char*)&tSendTimeOut, sizeof(tSendTimeOut)))
{
DisConnect();
return false;
}
if (SOCKET_ERROR == setsockopt(m_sclient, SOL_SOCKET, SO_RCVTIMEO, (char*)&tRecvTimeOut, sizeof(tRecvTimeOut)))
{
DisConnect();
return false;
}
//设置为不延时发送
int v2 = 1;
if (SOCKET_ERROR == setsockopt(m_sclient, IPPROTO_TCP, TCP_NODELAY, (const char*)&v2, sizeof(v2)))
{
DisConnect();
return false;
}
*/
//设置为非阻塞模式
u_long u1 = 1;
if (SOCKET_ERROR == ioctlsocket(m_socketClient, FIONBIO, &u1))
{
DisConnect();
return false;
}
SOCKADDR_IN addrSrv;
memset((char*)&addrSrv, 0, sizeof(addrSrv));
addrSrv.sin_addr.S_un.S_addr = inet_addr(strIp); //设定需要连接的服务器的ip地址
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(Port); //设定需要连接的服务器的端口地址
//Sleep(500);
bool bRet = false;
int nRet = 0;
for (int nLoop = 0; nLoop < 2; nLoop++)
{
int iRtn = connect(m_socketClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (iRtn == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK != WSAGetLastError())//非阻塞 不能马上连上的,会返回这个状态
{
DisConnect();
return false;
}
}
//select超时时间设置
fd_set fd;
FD_ZERO(&fd);
FD_SET(m_socketClient, &fd);
struct timeval tConnectTimeOut = { 0,500000 }; //连接超时时间500ms
nRet = select(0, 0, &fd, 0, &tConnectTimeOut);
if (nRet <= 0)
{
bRet = false;
continue;
}
else
{
bRet = true;
break;
}
}
//连接失败
if (!bRet)
{
DisConnect();
return false;
}
m_bConnectOK = true;
//if (m_ConnectChangeFun)
// (*m_ConnectChangeFun)(m_bConnectOK);
return true;
}
bool TcpClinet::isActive()
{
int opt_val;
socklen_t opt_len = sizeof(opt_val);
int error = -1, len2;
len2 = sizeof(int);
int r = getsockopt(m_socketClient, SOL_SOCKET, SO_KEEPALIVE, (char*)&error, &len2);
if (r != 0 || error == -1)
{
if (!Connect())
{
return false;
}
}
return true;
}
void TcpClinet::DisConnect(bool bMutex)
{
if (m_socketClient != SOCKET_ERROR)
{
closesocket(m_socketClient);
//WSACleanup();
}
m_bConnectOK = false;
m_socketClient = SOCKET_ERROR;
//if (m_ConnectChangeFun)
// (*m_ConnectChangeFun)(m_bConnectOK);
}
bool TcpClinet::clearBuf_c()
{
DWORD initTime = GetTickCount();
do
{
if (0 <= recv(m_socketClient, m_recvBuffer, CHAR_LEN, 0))
return true;
if (abs(int(GetTickCount() - initTime)) > 1000)
return false;
} while (1);
return false;
}
bool TcpClinet::recvBuf_c(char* pStr, int& len, int waitTimeMS)
{
QMutexLocker locker(&m_Mutex);
if (!isActive())
return false;
memset(m_recvBuffer, '\0', CHAR_LEN);
int buflen;
DWORD initTime = GetTickCount();
while (true)
{
buflen = recv(m_socketClient, m_recvBuffer, CHAR_LEN, 0);
if (buflen > 0)
{
memcpy(pStr, m_recvBuffer, buflen);
len = buflen;
return true;
}
//当接受数据时断开连接会返回0
else if (buflen == 0)
{
Connect();
return false;
}
//初始等待连接或是已连接未收到数据返回-1
else if (buflen < 0)
{
if (!m_bConnectOK)
Connect();
if (abs(int(GetTickCount() - initTime)) > waitTimeMS)
return false;
}
}
return true;
}
bool TcpClinet::sendBuf_c(char const *pStr, const int& len)
{
QMutexLocker locker(&m_Mutex);
if (!isActive())
return false;
int rtn = send(m_socketClient, pStr, len, 0);
if (rtn < 0)
{
Connect();
return false;
}
return true;
}
/*__________________________TCP-Server__________________________________*/
TcpServer::TcpServer(void)
{
m_socketServer = SOCKET_ERROR;
m_socketClient = SOCKET_ERROR;
m_ServerOK = false;
m_typeName = "TCP-服务器";
}
TcpServer::TcpServer(const std::string& IP, int Port)
: ISocketBaese(IP, Port, SOCKET_TYPE_TCP_SERVER)
{
m_socketServer = SOCKET_ERROR;
m_socketClient = SOCKET_ERROR;
m_ServerOK = false;
m_typeName = "TCP-服务器";
}
TcpServer::~TcpServer(void)
{
}
bool TcpServer::Connect(bool bMutex)
{
if (bMutex)
{
QMutexLocker locker(&m_Mutex);
if (m_ServerOK)
return ConnectClient();
return Connect(m_IP, m_Port);
}
if (m_ServerOK)
return ConnectClient();
return Connect(m_IP, m_Port);
}
bool TcpServer::ConnectClient()
{
SOCKADDR_IN addrClt;
int len = sizeof(SOCKADDR_IN);
SOCKET socket = accept(m_socketServer, (SOCKADDR*)&addrClt, &len);
if (socket != SOCKET_ERROR)
{
m_socketClient = socket;
m_bConnectOK = true;
m_socketClientList.push_back(socket);
return true;
}
return false;
}
bool TcpServer::Connect(std::string IP, int Port)
{
DisConnect();
char strIp[1024];
memset(strIp, '\0', 1024);
memcpy(strIp, IP.c_str(), IP.length());
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);//该函数的功能是加载一个Winsocket库版本
if (err != 0)
return false;
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
DisConnect();
return false;
}
m_socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socketServer == INVALID_SOCKET)
{
DisConnect();
return false;
}
//设置为非阻塞模式
u_long u1 = 1;
if (SOCKET_ERROR == ioctlsocket(m_socketServer, FIONBIO, &u1))
{
DisConnect();
return false;
}
SOCKADDR_IN addrSrv;
memset((char*)&addrSrv, 0, sizeof(addrSrv));
addrSrv.sin_addr.S_un.S_addr = inet_addr(strIp); //设定需要连接的服务器的ip地址
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(Port); //设定需要连接的服务器的端口地址
//Sleep(500);
bool bRet = false;
int nRet = 0;
int iRtn = bind(m_socketServer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (iRtn == SOCKET_ERROR)
{
if (WSAEWOULDBLOCK != WSAGetLastError())//非阻塞 不能马上连上的,会返回这个状态
{
DisConnect();
return false;
}
}
//监听
if (SOCKET_ERROR == listen(m_socketServer, 1))
{
DisConnect();
return false;
}
m_ServerOK = true;
return ConnectClient();
}
void TcpServer::DisConnect(bool bMutex)
{
for (auto& it : m_socketClientList)
{
closesocket(it);
}
m_socketClientList.clear();
if (m_socketServer != SOCKET_ERROR)
closesocket(m_socketServer);
//WSACleanup();
m_socketServer = SOCKET_ERROR;
m_socketClient = SOCKET_ERROR;
m_bConnectOK = false;
m_ServerOK = false;
}
bool TcpServer::clearBuf_c()
{
DWORD initTime = GetTickCount();
do
{
bool falg = 0;
for (auto&it : m_socketClientList)
{
if (0 > recv(it, m_recvBuffer, CHAR_LEN, 0))
falg = 1;
}
if (falg == 0) return true;
if (abs(int(GetTickCount() - initTime)) > 1000)
return false;
} while (1);
return false;
}
bool TcpServer::recvBuf_c(char* pStr, int& len, int waitTimeMS)
{
QMutexLocker locker(&m_Mutex);
memset(m_recvBuffer, '\0', CHAR_LEN);
int buflen;
DWORD initTime = GetTickCount();
while (true)
{
for (auto&it : m_socketClientList)
{
m_socketClient = it;
buflen = recv(m_socketClient, m_recvBuffer, CHAR_LEN, 0);
if (buflen > 0)
{
memcpy(pStr, m_recvBuffer, buflen);
len = buflen;
return true;
}
//当接受数据时断开连接会返回0
else if (buflen == 0)
{
m_socketClientList.remove(it);
if (m_socketClientList.size() == 0)
{
m_socketClient = SOCKET_ERROR;
m_bConnectOK = false;
}
Connect();
return false;
}
//初始等待连接或是已连接未收到数据返回-1
else if (buflen < 0)
{
Connect();
if (abs(int(GetTickCount() - initTime)) > waitTimeMS)
return false;
}
}
}
return true;
}
bool TcpServer::sendBuf_c(char const *pStr, const int& len)
{
QMutexLocker locker(&m_Mutex);
memset(m_sendBuffer, '\0', CHAR_LEN);
memcpy(m_sendBuffer, pStr, len);
int rtn = send(m_socketClient, m_sendBuffer, len, 0);
if (rtn < 0)
{
Connect();
return false;
}
return true;
}