#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QTcpSocket"
#include "QMessageBox"
#include "qtextcodec.h"
#include <QDateTime>
#include <QString>
#include <QDebug>
#include <stdio.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
socket = new QTcpSocket;
//连接信号槽
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
ui->textEdit_Recv->setReadOnly(true);
ui->pushButton_Send->setEnabled(false);
ui->lineEdit_IP->setText("127.0.0.1"); //设置连接服务器的IP
ui->lineEdit_Port->setText("8080"); //设置连接端口
}
MainWindow::~MainWindow()
{
delete ui;
}
//点击连接按钮
void MainWindow::on_pushButton_Connect_clicked()
{
if(ui->pushButton_Connect->text() == tr("连接"))
{
QString IP;
int port;
//获取IP地址
IP = ui->lineEdit_IP->text();
//获取端口号
port = ui->lineEdit_Port->text().toInt();
ui->textEdit_Recv->setText("");
ui->textEdit_Recv->insertPlainText("正在连接"+ui->lineEdit_IP->text()+":"+ui->lineEdit_Port->text()+"\n");
//取消已有的连接
socket->abort();
//连接服务器
socket->connectToHost(IP, port);
//等待连接成功
if(!socket->waitForConnected(30000))
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));
QMessageBox::warning(this,tr("消息"),tr("连接失败!请重新连接"),QMessageBox::Yes);
ui->textEdit_Recv->insertPlainText("连接失败\n");
return;
}
ui->textEdit_Recv->insertPlainText("连接成功\n");
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));
QMessageBox::information(this,tr("消息"),tr("连接成功"),QMessageBox::Yes);
//发送按键使能
ui->pushButton_Send->setEnabled(true);
//修改按键文字
ui->pushButton_Connect->setText(tr("断开连接"));
}
else
{
//断开连接
ui->textEdit_Recv->setText(tr("断开连接\n"));
socket->disconnectFromHost();
//修改按键文字
ui->pushButton_Connect->setText("连接");
ui->pushButton_Send->setEnabled(false);
}
}
//点击发送按钮 考虑发送结构体消息
void MainWindow::on_pushButton_Send_clicked()
{
sendData st_senddata;
QByteArray get_data, sendTcpData;
char *temp;
QString str;
//senddata.header.resize(2);
st_senddata.header[0] = 0x55;
st_senddata.header[1] = 0xAA;
str = ui->textEdit_Send->toPlainText().toLocal8Bit();
if(str.length() > 64)
{
QMessageBox::information(this,tr("提示"),tr("数据长度限制为64!"),QMessageBox::Yes);
ui->textEdit_Send->clear();
return;
}
get_data=(QByteArray)ui->textEdit_Send->toPlainText().toLocal8Bit(); //直接获取用户输入同时将QString转成QByteArray
temp=get_data.data(); //将QByteArray转成char*
memcpy(st_senddata.my_data,temp,get_data.length()); //不拷贝内存传结构体时就只会传一个指针过去
//数据长度
st_senddata.dataLength = get_data.length();
//校验和
st_senddata.check_sum = get_data.length() + 3;
//使用字节数组,将结构体转为字符数组,发送的是字符数组(数据在传输过程中都是byte类型的)
sendTcpData.resize((get_data.length()+3)); //直接sizeof(senddata)内存会变小,设置了对齐方式解决,,,只给他赋予数据长度加帧头、校验和所占字节
memcpy(sendTcpData.data(),&st_senddata,(get_data.length()+3));
sendTcpData.append(st_senddata.check_sum);
//memcpy只能处理字段为基本类型的结构体, 当使用QString name, 用person->name去访问其值, 程序崩溃; 由此可见,内存数据无法还原构建成QString类. 如果要写入自定的QT类, 只能借助QBuffer了, 通过二进制流写入
socket->write(sendTcpData);
ui->textEdit_Recv->insertPlainText("send:"+str+"\n");
socket->flush(); //释放socket缓存
ui->textEdit_Send->clear(); //发送出去后将发送文本清空
//释放指针、清空QByteArray数组
free(temp);
temp = NULL;
get_data.clear();
get_data.squeeze();
sendTcpData.clear();
sendTcpData.squeeze();
}
//接收数据 考虑:结构体消息强转时消息未充满处理
void MainWindow::socket_Read_Data()
{
sendData st_receiveTcpData, *get_Data;
QByteArray buffer;
QString str;
//读取缓冲区数据
buffer = socket->readAll();
if(!buffer.isEmpty())
{
memset(&st_receiveTcpData,0,sizeof (st_receiveTcpData));
get_Data = (sendData*)buffer.data(); //强转为结构体,需要用结构体指针接收
//读取帧头
for(int i = 0; i < sizeof (st_receiveTcpData.header); i++)
{
st_receiveTcpData.header[i] = get_Data->header[i];
}
//读取数据长度
st_receiveTcpData.dataLength = get_Data->dataLength;
//读取数据
for(int i = 0; i < buffer.length() - 4; i++)//buffer的长度减去header、datalength、check_sum的长度就是数据的长度
{
st_receiveTcpData.my_data[i] = get_Data->my_data[i];
}
//读取校验和
get_Data->check_sum = get_Data->my_data[buffer.length()-4];
st_receiveTcpData.check_sum = get_Data->check_sum;
//将my_data数据转为QString
str = QString(QLatin1String(st_receiveTcpData.my_data));
//将my_data在文本框显示
ui->textEdit_Recv->insertPlainText("receive:"+str+"\n");
//释放内存
free(get_Data);
buffer.clear();
buffer.squeeze();
}
}
//连接断开
void MainWindow::socket_Disconnected()
{
//发送按键失能
ui->pushButton_Send->setEnabled(false);
//修改按键文字
ui->pushButton_Connect->setText("连接");
qDebug() << "Disconnected!";
}