QT实现TCP通信程序虚心请教
本人大四做毕设时需要QT实现TCP通信,目前程序通过相关参考已经编好,在自己PC上打开两个进程也可以实现相应功能;但是当将该程序用两个PC(这两个PC已接入局域网)分别运行时,一个作为服务器、一个作为客户端运行时,不可以正常连接,运行客户端的PC连接不到服务器的进程上。
已做尝试
- 两台PC分别可以Ping到对方;
- 尝试将两台PC的防火墙均关闭;
- 两台PC的IP为XXX.XXX.XXX.30/XXX.XXX.XXX.31;
- netsh allow端口也尝试过;
虚心请教
本人小白一枚,尝试过以上四种方法均不可以,虚心求教:
- 如何实现两台在同一局域网的PC的TCP通信;
- 如何利用QT实现广域网的两台PC的TCP通信;
源代码附上~谢谢各位大佬
QT .h文件
#ifndef MYTCP_H
#define MYTCP_H
#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QFile>
#include <QTimer>
#include <QMessageBox>
#include <QVector>
namespace Ui {
class mytcp;
}
class mytcp : public QMainWindow
{
Q_OBJECT
public:
explicit mytcp(QWidget *parent = nullptr);
~mytcp();
private:
Ui::mytcp *ui;
private slots:
void on_severRB_clicked();//选择作为服务器
void on_clientRB_clicked();//选择作为客户端
void on_StartBt_clicked();//启动服务器或链接客户端
void on_closeBt_clicked();//关闭服务器或断开客户端
void on_onlineUserList_doubleClicked(const QModelIndex &index);//选择给哪个客户端发送数据
void on_autoCB_clicked(bool checked);//选择自动发送还是手动发送
void on_sendMsgBt_clicked();//发送信息
void ReadError(QAbstractSocket::SocketError);
//服务器
void accept_connect();//与newconnection信号关联
void recv_data(); //接收数据
void auto_time_send();//定时器定时发送数据
void client_disconnect();//关联掉线信号
void connect_suc();//检测客户端连接成功信号
void on_clearRcvBt_clicked();
void on_clearSendBt_clicked();
private:
QTimer *mTimer;//定时发送数据
QTcpServer *mServer;
QTcpSocket *mSocket;
QVector<QTcpSocket*> clients; //存储所有在线客户端(容器)
bool isServer;//标志位,true为服务器,false为客户端
//保存接收和发送数据的字节数
qint64 recvSize;
qint64 sendSize;
qint16 onNum;
bool isCheckServer;//判断是否选择了服务器
bool isCheckClient;//判断是否选择了客户端
};
#endif // MYTCP_H
QT .cpp文件
#include "mytcp.h"
#include "ui_mytcp.h"
#include <QPushButton>
#include <QDebug>
mytcp::mytcp(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::mytcp),
onNum(0)
{
ui->setupUi(this);
this->setFixedSize(513,490);
this->setWindowTitle("TCP数据通信");
recvSize = 0;
sendSize = 0;
//初始化定时器
mTimer = new QTimer();
connect(mTimer,SIGNAL(timeout()),this,SLOT(auto_time_send()));
//隐式connect 不需要在显式connect
//connect(ui->radioClient, SIGNAL(toggled(bool)), this , SLOT(on_clientRB_clicked()));
//connect(ui->radioServer, SIGNAL(toggled(bool)), this, SLOT(on_severRB_clicked()));
}
mytcp::~mytcp()
{
delete ui;
}
//与newconnection信号关联
void mytcp::accept_connect()
{
mSocket = mServer->nextPendingConnection(); //返回与客户端连接通信的套接字
//关联接收数据信号
connect(mSocket, SIGNAL(readyRead()),this,SLOT(recv_data()));
//关联掉线信号
connect(mSocket, SIGNAL(disconnected()),this,SLOT(client_disconnect()));
//上线用户添加到客户列表容器
clients.append(mSocket);
//把用户添加到界面列表中
QString ip = mSocket->peerAddress().toString().remove("::ffff:");//去除客户端中多余的字符
ui->onlineUserList->addItem(ip);
//在线数量添加
onNum++;
ui->onlineUserCount->setText(QString::number(onNum));//显示在线数
}
//接收数据
void mytcp::recv_data()
{
QTcpSocket *obj = (QTcpSocket*)sender();
//获取发送数据端的IP
QString ip = obj->peerAddress().toString();
ip.remove("::ffff:");
QString msg = obj->readAll();
ui->receiveList->addItem(ip+":"+msg);//显示接收到的数据
recvSize += msg.size();//统计接收到的数据的字节数
ui->receiveNumLabel->setText(QString::number(recvSize));
}
void mytcp::client_disconnect()
{
QTcpSocket *obj = (QTcpSocket*)sender();//获取掉线对象
if(isServer)
{
int row = clients.indexOf(obj);//找到掉线对象的内容所在的行
QListWidgetItem *item = ui->onlineUserList->takeItem(row);//从界面列表中去除找到的一行内容
delete item;
clients.remove(row);//从容器中删除对象
//掉线时删除在线数量
onNum--;
ui->onlineUserCount->setText(QString::number(onNum));
}
else
{
ui->StartBt->setEnabled(true);//断开连接的时候重新启用开始按钮
}
}
//客户端连接成功
void mytcp::connect_suc()
{
ui->StartBt->setEnabled(false);//连接成功则禁用开始按钮
qDebug() << "建立连接成功";
}
//定时器定时发送数据
void mytcp::auto_time_send()
{
qint64 len = mSocket->write(ui->sendMsgEdit->toPlainText().toUtf8());
if(len > 0)
{
sendSize += len;//统计发送的字节数
ui->sendNumLabel->setText(QString::number(sendSize));//把发送的字节数显示到sendNumLabel上
}
}
//选择作为服务器
void mytcp::on_severRB_clicked()
{
this->isCheckServer = true;
this->isServer = true;
//获取本地ip显示在IpEdit中
ui->IpEdit->setText(QHostAddress(QHostAddress::LocalHost).toString());
ui->IpEdit->setEnabled(false);//关闭ip输入编辑器
this->isCheckClient = false;
qDebug() << "选中了服务器";
}
//选择作为客户端
void mytcp::on_clientRB_clicked()
{
this->isCheckClient = true;
this->isServer = false;
ui->IpEdit->setEnabled(true);//打开ip输入编辑器
this->isCheckServer = false;
qDebug() << "选中了客户端";
}
//启动服务器或者连接服务器
void mytcp::on_StartBt_clicked()
{
if(isServer) //服务器
{
qDebug() << "正在开启服务器";
mServer = new QTcpServer();
//关联新客户端链接信号
connect(mServer,SIGNAL(newConnection()),this,SLOT(accept_connect()));
mServer->listen(QHostAddress::Any,ui->PortEdit->text().toInt());//启动服务器监听
ui->StartBt->setEnabled(false);//开始按钮禁用
qDebug() << "开启成功,正在监听。";
}
if(!isServer) //客户端
{
qDebug() << "正在连接服务器";
mSocket = new QTcpSocket();
//设置服务器的 ip和端口号
mSocket->connectToHost(ui->IpEdit->text(),ui->PortEdit->text().toInt());
//检测链接成功信号
if (mSocket->waitForConnected(1000)) // 连接成功则进入if{}
{
qDebug() << "连接成功";
}
connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));
connect(mSocket, SIGNAL(error(QAbstractSocket::SocketError)), \
this, SLOT(ReadError(QAbstractSocket::SocketError)));
//关联接收数据信号
connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data()));
//关联掉线信号
connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect()));
}
if(isCheckServer == false && isCheckClient == false)//如果两个都没选择
{
QMessageBox::warning(this,"提示","请选择服务器或者客户端");
ui->StartBt->setEnabled(true);
return;
}
if(isCheckServer)//选择了服务器
{
if(ui->PortEdit->text().isEmpty() || ui->PortEdit->text() == "请输入端口号")
{
QMessageBox::warning(this,"提示","请输入端口号");
ui->StartBt->setEnabled(true);
return;
}
}
if(isCheckClient)//选择了客户端
{
if(ui->IpEdit->text().isEmpty() || ui->IpEdit->text() == "请输入ip" || ui->IpEdit->text() == "请输入端口号")
{
QMessageBox::warning(this,"提示","请输入ip和端口号");
ui->StartBt->setEnabled(true);
return;
}
}
}
//关闭服务器或者断开
void mytcp::on_closeBt_clicked()
{
if(isServer)//服务器
{
for(int i=0;i<clients.count();i++)
{
clients.at(i)->close();//关闭所有客户端
}
//关闭所有服务器之后开始按钮才能启用
mServer->close();
ui->StartBt->setEnabled(true);
}
else //客户端
{
mSocket->close();//关闭客户端
ui->StartBt->setEnabled(true);//启用开始按钮
}
}
//双击选择要发送的客户端
void mytcp::on_onlineUserList_doubleClicked(const QModelIndex &index)
{
mSocket = clients.at(index.row());
}
//自动发送数据
void mytcp::on_autoCB_clicked(bool checked)
{
if(checked)
{
if(ui->autoTimeEdit->text().toInt() <= 0)
{
QMessageBox::warning(this,"提示","请输入时间值ms");
ui->autoCB->setChecked(false);//把按钮重新置于没选中的状态
return;
}
mTimer->start(ui->autoTimeEdit->text().toInt());//启动定时器
}
else
{
mTimer->stop();//停止定时器
}
}
//手动发送数据
void mytcp::on_sendMsgBt_clicked()
{
auto_time_send();
}
//清空接收区
void mytcp::on_clearRcvBt_clicked()
{
ui->receiveNumLabel->clear();
this->recvSize = 0;
ui->receiveNumLabel->setText(QString::number(recvSize));
}
//清空发送区
void mytcp::on_clearSendBt_clicked()
{
ui->sendNumLabel->clear();
this->sendSize = 0;
ui->sendNumLabel->setText(QString::number(sendSize));
}
//错误显示槽函数
void mytcp::ReadError(QAbstractSocket::SocketError)
{
mSocket->disconnectFromHost();
QMessageBox msgBox;
msgBox.setText(tr("failed to connect server because %1").arg(mSocket->errorString()));
}