#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCompleter>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->combClient2ServerIP->setEditable(true);
ui->combClient2ServerPort->setEditable(true);
//利用QCompleter进行输入
QCompleter *pCompleter = new QCompleter(ui->combClient2ServerIP->model(), this);
pCompleter->setCaseSensitivity(Qt::CaseInsensitive);//不区分大小写
ui->combClient2ServerIP->setCompleter(pCompleter);
// 当用户完成输入后(例如按下了Enter键),但选择下拉框后并不会响应,而是要再次选择或者在别处点击才会
// 要和currentIndexChanged一起用
QObject::connect(ui->combClient2ServerIP->lineEdit(), &QLineEdit::editingFinished,
this, &MainWindow::OncombClient2ServerIpFinished);
QObject::connect(ui->combClient2ServerPort->lineEdit(), &QLineEdit::editingFinished,
this, &MainWindow::OncombClient2ServerPortFinished);
setWindowTitle("TCP服务端和客服端程序");
myServer = new QTcpServer(this);
clientList.clear();
serverList.clear();
}
MainWindow::~MainWindow()
{
delete ui;
}
/*--------------------------------服务端操作-------------------------------*/
/* 服务端IP和Port绑定按钮 */
void MainWindow::on_pushButtonServerSet_clicked()
{
QString myAddr;
myAddr = ui->lineEditServerIP->text(); // 手动设置ip
QString myPort = ui->lineEditServerPort->text();
QString msg;
bool ret = myServer->listen(QHostAddress(myAddr),myPort.toUInt());
if(!ret) {
msg = "服务端绑定失败!";
} else {
msg = "服务端绑定成功!";
ui->pushButtonServerSet->setEnabled(false);
}
ui->textBrowserInfo->append(msg);
myServer->setMaxPendingConnections(MAXNUM);
connect(myServer, &QTcpServer::newConnection, this, &MainWindow::OnServerNewConnection);
connect(myServer, &QTcpServer::acceptError, this, &MainWindow::OnServerError);
}
/* 服务端发送客户端按钮响应函数 */
void MainWindow::on_btnServerSend_clicked()
{
QString ip = ui->combServer2ClientIP->currentText();
QString port = ui->combServer2ClientPort->currentText();
// 查找对应的客户端
for(int i=0;i<clientList.length();i++) {
if(clientList.at(i)->peerAddress().toString()==ip) {
if(clientList.at(i)->peerPort() == port.toUInt()) {
QString msg = ui->textEditServer->toPlainText();\
clientList.at(i)->write(msg.toUtf8());
ui->textEditServer->clear(); // 清除发送框
break;
}
}
}
}
/* 更新服务端的客户端IP和Port下拉框 */
void MainWindow::UpdateServerComboBox()
{
QString ipStr = "", portStr = "";
ui->combServer2ClientIP->clear();
ui->combServer2ClientPort->clear();
foreach (QTcpSocket* tcp, clientList) {
QString ip = QString(tcp->peerAddress().toString());
if(-1 == ipStr.indexOf(ip)) {
ui->combServer2ClientIP->addItem(ip);
ipStr += ip;
}
QString port = QString("%1").arg(tcp->peerPort());
if(-1 == portStr.indexOf(port)) {
ui->combServer2ClientPort->addItem(port);
portStr += port;
}
}
}
/* 服务端连接成功响应 */
void MainWindow::OnServerNewConnection()
{
QTcpSocket *client = myServer->nextPendingConnection();
clientList.append(client);
QString msg = QString("客户端[%1:%2]连入!")
.arg(client->peerAddress().toString())
.arg(client->peerPort());
UpdateServerComboBox(); // 将新连接的客户端加入下拉框
ui->textBrowserInfo->append(msg);
connect(client, &QTcpSocket::disconnected, this, &MainWindow::OnServerDiconnected); // 客户端断开
connect(client, &QTcpSocket::readyRead, this, &MainWindow::OnServerReadyRead); // 读取内容
}
/* 与服务器连接的客户端断开响应 */
void MainWindow::OnServerDiconnected()
{
QTcpSocket *client = (QTcpSocket *)this->sender();
QString msg = QString("客户端[%1:%2]退出!")
.arg(client->peerAddress().toString())
.arg(client->peerPort());
ui->textBrowserInfo->append(msg);
for(int i= 0;i<clientList.length();i++) { // 删除对应客户端
if(clientList.at(i)->peerAddress() == client->peerAddress()) {
if(clientList.at(i)->peerPort() == client->peerPort()) {
clientList.removeAt(i);
break;
}
}
}
UpdateServerComboBox(); // 更新连接的客户端下拉框
}
/* 服务端读取客户端信息响应 */
void MainWindow::OnServerReadyRead()
{
QTcpSocket *client = (QTcpSocket *)this->sender();
QString str1 = QString(QString("客户端[%1:%2]说:")
.arg(client->peerAddress().toString())
.arg(client->peerPort()));
QString msg;
QString str2;
while (!client->atEnd()) {
msg.append(QString(client->readAll()));
}
str2 = QString("%1%2").arg(str1).arg(msg);
ui->textBrowserInfo->append(str2);
}
/* 服务端连接错误响应 */
void MainWindow::OnServerError(QAbstractSocket::SocketError socketError)
{
ui->textBrowserInfo->append(QString("服务端错误:%1").arg(socketError));
}
/*--------------------------------客户端操作-------------------------------*/
/* 根据IP和Port获取连接状态 */
int MainWindow::GetConnectState()
{
QString servIp = ui->combClient2ServerIP->currentText();
QString servPort = ui->combClient2ServerPort->currentText();
for(int i= 0;i<serverList.length();i++) { // 查找对应的服务端
if(serverList.at(i).ipStr == servIp) {
if(serverList.at(i).portStr == servPort) {
return serverList.at(i).tcp->state();
}
}
}
return QAbstractSocket::UnconnectedState;
}
/* 更新服务端的客户端IP和Port下拉框
* 先清空下拉框,再添加;如果不清空,则编辑的新项与原项index一样,要重新选择后才会改变。
*/
void MainWindow::UpdateClientComboBox(QString ipStr, QString portStr)
{
QString tmpIpStr = ui->combClient2ServerIP->currentText();
QString tmpPortStr = ui->combClient2ServerPort->currentText();
ipStr.clear();
portStr.clear();
ui->combClient2ServerIP->clear();
ui->combClient2ServerPort->clear();
foreach (mServer mSer, serverList) {
if(-1 == ipStr.indexOf(mSer.ipStr)) {
ui->combClient2ServerIP->addItem(mSer.ipStr);
ipStr += mSer.ipStr;
}
if(-1 == portStr.indexOf(mSer.portStr)) {
ui->combClient2ServerPort->addItem(mSer.portStr);
portStr += mSer.portStr;
}
}
ui->combClient2ServerIP->setCurrentText(tmpIpStr); // 设置为当前的值
ui->combClient2ServerPort->setCurrentText(tmpPortStr); //
}
/* 连接服务器 */
void MainWindow::ConnectClient2Server()
{
mServer tmpServer;
tmpServer.ipStr = ui->combClient2ServerIP->currentText();
tmpServer.portStr = ui->combClient2ServerPort->currentText();
for(int i= 0;i<serverList.length();i++) { // 查找对应的服务端
if((serverList[i].ipStr == tmpServer.ipStr) &&
(serverList[i].portStr == tmpServer.portStr) ) {
// 可以重新发起一次连接...
if(serverList[i].tcp == nullptr) {
serverList[i].tcp = new QTcpSocket(this);
}
serverList[i].tcp->abort();
serverList[i].tcp->connectToHost(QHostAddress(serverList[i].ipStr),