头文件
#ifndef TCPSOCKET_H
#define TCPSOCKET_H
#include <windows.h> //windows socket
#include <winsock2.h> //windows socket 头文件
#include <QThread>
class RecvThread:public QObject
{
Q_OBJECT
public:
SOCKET *tcpSpcket;
bool bRun=true;
RecvThread();
virtual ~RecvThread();
public slots:
void Recv();
signals:
void ToRecv();
void ToShow(QString);
};
class TcpSocket
{
public:
TcpSocket();
virtual ~TcpSocket();
void SetSocketNoblock();
void connectToServer();
void CloseSocket();
void Send(QByteArray data);
SOCKET tcpSpcket;
sockaddr_in remoteAddr;
bool connected=false;
QThread recvThread;
RecvThread recvThreadObject;
};
#endif // TCPSOCKET_H
cpp
#include "tcpsocket.h"
#include <QDebug>
TcpSocket::TcpSocket()
{
//win socket 初始化
WORD sockVersion=MAKEWORD(2,2);
WSADATA wsaData;
if(WSAStartup(sockVersion,&wsaData)!=0)
{
qDebug()<<"ERROR"<<__FUNCTION__<<__LINE__;
}
else
{
qDebug()<<"SUCESS"<<__FUNCTION__<<__LINE__;
}
//启动接收子线程
recvThreadObject.moveToThread(&recvThread);
recvThread.start(QThread::HighPriority);
emit recvThreadObject.ToRecv();
}
TcpSocket::~TcpSocket()
{
qDebug()<<__LINE__;
recvThreadObject.bRun=false;
SetSocketNoblock();
recvThread.quit();
recvThread.wait();
CloseSocket();
}
void TcpSocket::SetSocketNoblock()
{
u_long argp = 1;
ioctlsocket(tcpSpcket, FIONBIO, &argp);
}
void TcpSocket::connectToServer()
{
qDebug()<<"123456";
//申请socket
if(!connected)
{
tcpSpcket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//使用端口服用技术
int opt=1;
setsockopt(tcpSpcket,SOL_SOCKET,SO_REUSEADDR,(const char *)&opt,sizeof (opt));
struct linger myLinger;
myLinger.l_onoff=1;
myLinger.l_linger=0;
setsockopt(tcpSpcket,SOL_SOCKET,SO_LINGER,(const char *)&myLinger,sizeof (myLinger));
//客户端指定端口与服务端通信
struct sockaddr_in client_addr;
client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(60000);
bind(tcpSpcket,(struct sockaddr *)(&client_addr),sizeof (sockaddr));
//将socket设置成阻塞模式
u_long argp = 1;
qDebug()<<ioctlsocket(tcpSpcket, FIONBIO, &argp);
//设置缓冲大小
int recvBufSize=2592*2048*7;
setsockopt(tcpSpcket,SOL_SOCKET,SO_RCVBUF,(const char *)&recvBufSize,sizeof(int));
//设置接收超时
int time=500;
setsockopt(tcpSpcket,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(int));
//设置要链接的TcpServer
remoteAddr.sin_addr.S_un.S_addr=inet_addr("192.168.1.2");
remoteAddr.sin_port=htons(60000);
remoteAddr.sin_family=AF_INET;
//将socket传输到子线程
recvThreadObject.tcpSpcket=&tcpSpcket;
int ret=connect(tcpSpcket, (SOCKADDR*)&remoteAddr, sizeof(SOCKADDR));
if(ret==0)
{
connected=true;
}
}
}
void TcpSocket::CloseSocket()
{
closesocket(tcpSpcket);
QThread::msleep(500);
connected=false;
// shutdown(tcpSpcket,SD_BOTH);
}
void TcpSocket::Send(QByteArray data)
{
send(tcpSpcket,data.toStdString().c_str(),data.length(),0);
}
RecvThread::RecvThread()
{
connect(this,SIGNAL(ToRecv()),this,SLOT(Recv()));
}
RecvThread::~RecvThread()
{
qDebug()<<__LINE__;
bRun=false;
QThread::msleep(1);
}
void RecvThread::Recv()
{
char buf[1024]={0};
sockaddr sin;
int formLen=sizeof (sin);
while (bRun)
{
memset(buf,0,1024);
qDebug()<<"123:"<<tcpSpcket;
int recvLen= recvfrom(*tcpSpcket,(char*)buf,1024,0,&sin,&formLen);
if(recvLen>0)
{
emit ToShow(buf);
qDebug()<<"123456";
}
}
}
使用方法:
在mainWindows中声明TcpSocket类。然后调用Tcp的connectToServer,Send(DATA),CloseSocket() 方法使用