1、TCP/IP 通信有2种形式
1、client与server 通信,收发只有1个 端口;
2、client 与server通信,收发有2个 端口;(客户端里面起了一个server监听端口)
2、本文介绍第一种方式。
第一种方式,有2种方法实现。
a. 直接用SocketSend->readAll()
b. 配合使用 QT自带的SIGNAL readyRead()(注意线程问题)
实现如下代码
1. 头文件
#ifndef HSPOSEXTSOCKET_H
#define HSPOSEXTSOCKET_H
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QTcpServer>
#include <QThread>
#include <QMutex>
#define WAY2 0
class HSPOSEXTSOCKETSHARED_EXPORT HsPosExtSocket : public QTcpSocket
{
Q_OBJECT
QObject(parent);
public:
HsPosExtSocket(QObject *parent = NULL);
bool CallSocket(QString input,QString &outPut); //socket发送(封装)
bool Connect(QString serverip, int sendport, QString &ErrMsg); //socket连接(封装)
private:
QString ReadBuf; //读取数据保存
QHostAddress* HostSend;
QTcpSocket *SocketSend;
bool SocketConnect(QString serverip, int sendport); //TCP连接
bool SendSocketData(QString inPutMsg , QString& outPutMsg); //tcp发送数据,同一端口,返回
#if WAY2
QMutex mutex;
private slots:
void ReadMessage(); //读取数据槽函数
#endif
};
#endif // HSPOSEXTSOCKET_H
2. 源文件
#include "HsPosExtSocket.h"
#include <QTextCodec>
#include <QThread>
/***
* Function: 初始化
* Return:
**/
HsPosExtSocket::HsPosExtSocket(QObject *parent) :QTcpSocket(parent)
{
HostSend = new QHostAddress();
SocketSend = new QTcpSocket();
ReadBuf.clear();
#if WAY2
/* 绑定 接收触发信号 */
connect(SocketSend,SIGNAL(readyRead()),this,SLOT(ReadMessage()));
#endif
}
/***
* Function: SOCKET连接函数
* Return:
**/
bool HsPosExtSocket::Connect(QString serverip, int sendport, QString &ErrMsg)
{
if(NULL == HsPosStaticVariable::PosData.DataPlugin)
{
//PosLog.log->error("DataPlugin is null");
return false;
}
return SocketConnect(serverip , sendport);
}
/***
* Function: SOCKET连接请求函数
* Return:
**/
bool HsPosExtSocket::SocketConnect(QString serverip, int sendport)
{
if(!HostSend->setAddress(serverip))
{
//PosLog.log->info("欧尚: socket send ip error!");
return false;
}
SocketSend->connectToHost(*HostSend, sendport);
if (SocketSend->waitForConnected())
{
//PosLog.log->info("欧尚: socket connect success!");
}
else
{
//PosLog.log->info("欧尚: socket connect timeout!");
return false;
}
return true;
}
/***
* Function: SOCKET数据发送入口
* Return:
**/
bool HsPosExtSocket::CallSocket_2(QString input, QString &outPut)
{
bool ret;
if(SendSocketData(input, outPut))
{
ret = true;
}
else
{
ret = false;
}
return ret;
}
/***
* Function: SOCKET发送数据
* para:
* para:
* Return:
**/
bool HsPosExtSocket::SendSocketData(QString inPutMsg , QString& outPutMsg)
{
bool Ret = false;
outPutMsg.clear();
/* 向服务器写入信息 */
SocketSend->write(inPutMsg.toUtf8());
SocketSend->waitForBytesWritten();
/* 阻塞等待接受消息 */
SocketSend->waitForReadyRead(60000);
do
{
if(ReadBuf.length() > 1000)
{
/* 阻塞等待接收消息 */
SocketSend->waitForReadyRead(1000);
}
ReadBuf.clear();
ReadBuf = SocketSend->readAll();
outPutMsg.append(ReadBuf);
}while(ReadBuf.length() > 1000);
return Ret;
}
#if WAY2
/***
* Function: SOCKET发送数据
* Return:
**/
bool HsPosExtSocket::SendSocketData(QString inPutMsg , QString& outPutMsg)
{
outPutMsg.clear();
/* 向服务器写入信息 */
SocketSend->write(inPutMsg.toUtf8());
SocketSend->waitForBytesWritten();
/* 阻塞等待接受消息 */
SocketSend->waitForReadyRead(60000); //等待服务器返回,超时60s
QThread::msleep(100); //保证信号先触发eadMessage()
mutex.lock();
while(ReadBuf.length() > 1000) //如果socket发送数据太多,可能分多次发过来
{
outPutMsg.append(ReadBuf);
ReadBuf = "";
/* 阻塞等待接收消息 */
SocketSend->waitForReadyRead(1000);
}
outPutMsg.append(ReadBuf);
ReadBuf.clear();
mutex.unlock();
return true;
}
/***
* Function: SOCKET读取服务器返回数据
* Return:
**/
void HsPosExtSocket::ReadMessage()
{
mutex.lock();
////PosLog.log->info("enter ReadMessage");
ReadBuf.clear();
QByteArray RetData;
if(SocketSend->bytesAvailable() > 0)
{
RetData = SocketSend->readAll();
}
ReadBuf = RetData;
mutex.unlock();
}
#endif