Qt框架下服务器的实现

打印 上一主题 下一主题

主题 552|帖子 552|积分 1656

一、媒介

Qt框架提供了QTcpServe和QTcpSocket两种类实现TCP协议的相关毗连,TCP协议不再过多赘述,以下主要讲述自机服务器和自机客户端的毗连实现TCP协议通讯的详细方式。
二、根本功能介绍

利用Qt网络模块之前必要在.pro文件种加入network
服务器端

绑定端口,并通过信号判断新连入客户机,同时输出相关内容,同时通过断连信号举行客户端的删除。
收信功能绑定读取信号槽函数,对所带数据举行读取显示。
发信功能找到对应的客户机地址和端口举行发信
客户机端

毗连端口
收信功能绑定读取信号槽函数
发信功能直接将发送数据写入设备
三、详细原理和代码实现

在.pro文件中加入network
  1. QT       += core gui network
复制代码
初始化并分配指针空间
  1. void Widget::Init()
  2. {
  3.     myClient = new QTcpSocket(this);
  4. }
复制代码

服务器端实现

1.ui设计

搭建IP地址框和端口框Line Edit,信息吸取框和发送框Tetx Edit,两个PushButton举行绑定和发送

2.IP绑定

通过listen方法指示服务器侦听地址、地址和端口端口上的传入毗连。如果端口为 0,则自动选择端口。如果 address 为 QHostAddress::Any,则服务器将侦听所有网络接口。
setEnable设置按钮是否可以利用
setMaxPendingConnection设置最大挂起客户机数量
  1. void Widget::on_btn_bind_clicked()
  2. {
  3.     QString myAddr;
  4.     //手动设置ip
  5.     myAddr = ui->ledit_serv_addr->text();
  6.     QString myPort = ui->ledit_serv_port->text();
  7.     QString msg;
  8.     bool ret = myServer->listen(QHostAddress(myAddr),myPort.toUInt());
  9.     if(!ret)
  10.     {
  11.         msg = "绑定失败";
  12.     }
  13.     else
  14.     {
  15.         msg = "绑定成功";
  16.         ui->btn_bind->setEnabled(false);
  17.     }
  18.     ui->textEdit->append(msg);
  19.     myServer->setMaxPendingConnections(MAXNUM);
  20.     connect(myServer,SIGNAL(newConnection()),this,SLOT(doProcessNewConnection()));
  21.     connect(myServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),
  22.             this,SLOT(doProcessAcceptError(QAbstractSocket::SocketError)));
  23. }
复制代码
3.客户端连入

nextPendingConnection(),用于等候并担当下一个挂起的毗连。当一个客户端请求毗连时,服务器会将该毗连挂起,等候服务器担当毗连。nextPendingConnection()函数会阻塞当前线程,直到有一个毗连被担当。一旦有毗连被担当,会返回一个QTcpSocket对象。
此时对客户端的IP地址和端标语举行读取并显示
  1. void Widget::doProcessNewConnection()
  2. {
  3.     client = myServer->nextPendingConnection();
  4.     arrayClient.append(client);
  5.     QString msg = QString("客户端[%1:%2] 连入!")
  6.             .arg(client->peerAddress().toString())
  7.             .arg(client->peerPort());
  8.     ui->textEdit->append(msg);
  9.     //客户端断开
  10.     connect(client,SIGNAL(diconnected()),this,SLOT(doProcessDiconnected()));
  11.     //读取内容
  12.     connect(client,SIGNAL(readyRead()),this,SLOT(doProcessReadyRead()));
  13. }
复制代码
4.客户端退出

当客户端退出时,通过sender返回指向发送信号的对象的指针,同时遍历客户机列表删除对应的客户端
  1. void Widget::doProcessDiconnected()
  2. {
  3.     QTcpSocket *client = (QTcpSocket *)this->sender();
  4.     QString msg = QString("客户端[%1:%2] 退出!")
  5.             .arg(client->peerAddress().toString())
  6.             .arg(client->peerPort());
  7.     ui->textEdit->append(msg);
  8.     //删除对应客户端
  9.     for(int i= 0;i<arrayClient.length();i++)
  10.     {
  11.         if(arrayClient.at(i)->peerAddress() == client->peerAddress())
  12.         {
  13.             if(arrayClient.at(i)->peerPort() == client->peerPort())
  14.             {
  15.                 arrayClient.removeAt(i);
  16.                 break;
  17.             }
  18.         }
  19.     }
  20. }
复制代码
5.吸取信息

利用readyRead()信号,每当有新数据可用于从器件的当前读取通道读取时,该信号就会发出一次。将该信号内容举行循环读取并举行显示。
  1. void Widget::doProcessReadyRead()
  2. {
  3.     QTcpSocket *client = (QTcpSocket *)this->sender();
  4.     QString str1 = QString(QString("客户端[%1:%2] 说:")
  5.             .arg(client->peerAddress().toString())
  6.             .arg(client->peerPort()));
  7.     QString msg;
  8.     QString str2;
  9.     while (!client->atEnd())
  10.     {
  11.         msg.append(QString(client->readAll()));
  12.     }
  13.     str2 = QString("%1%2").arg(str1).arg(msg);
  14.     ui->textEdit->append(str2);
  15. }
复制代码
6.发送信息

读取输入的客户端IP和端口信息,遍历客户端列表,找到对应的客户端通过write举行数据写入。
  1. void Widget::on_btn_send_clicked()
  2. {
  3.     QString ip = ui->ledit_client_ip->text();
  4.     QString port = ui->ledit_client_port->text();
  5.     //查找对应的客户
  6.     for(int i=0;i<arrayClient.length();i++)
  7.     {
  8.         if(arrayClient.at(i)->peerAddress().toString()==ip)
  9.         {
  10.             if(arrayClient.at(i)->peerPort() == port.toUInt())
  11.             {
  12.                 QString msg = ui->textEdit_2->toPlainText();\
  13.                 arrayClient.at(i)->write(msg.toUtf8());
  14.                 ui->textEdit_2->clear();
  15.                 break;
  16.             }
  17.         }
  18.     }
  19. }
复制代码
客户机端实现

1.ui设计

搭建IP地址框和端口框Line Edit,信息吸取框和发送框Tetx Edit,两个PushButton举行毗连和发送

2.服务器毗连

connectTohost对指定的IP地址和端标语举行毗连,同时绑定四信号和槽函数
  1. void Widget::on_btn_bind_clicked()
  2. {
  3.     QString servIp = ui->ledit_serv_addr->text();
  4.     QString servPort = ui->ledit_serv_port->text();
  5.     myClient->connectToHost(QHostAddress(servIp),servPort.toUInt());
  6.     connect(myClient,SIGNAL(connected()),this,SLOT(doProcessConnected()));
  7.     connect(myClient,SIGNAL(readyRead()),this,SLOT(dorProcessReadyRead()));
  8.     connect(myClient,SIGNAL(disconnected()),this,SLOT(doProcessDisconnected()));
  9.     connect(myClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(doProcessError(QAbstractSocket::SocketError)));
  10. }
复制代码
3.信息吸取

readyRead信号举行读取,与服务器端相同
  1. void Widget::dorProcessReadyRead()
  2. {
  3.     QString msg,str1,str2;
  4.     str1 = QString(" 服务器[%1:%2] 说:")
  5.             .arg(myClient->peerAddress().toString())
  6.             .arg(myClient->peerPort());
  7.     while(!myClient->atEnd())
  8.     {
  9.         str2.append(QString(myClient->readAll()));
  10.     }
  11.     msg = QString("%1%2").arg(str1).arg(str2);
  12.     ui->textEdit->append(msg);
  13. }
复制代码
4.信息发送

write举行写入,与服务器端相同
  1. void Widget::on_btn_send_clicked()
  2. {
  3.     QString msg = ui->textEdit_2->toPlainText();
  4.     int ret = myClient->write(msg.toUtf8());
  5.     if(ret<=0)
  6.         return;
  7.     ui->textEdit_2->clear();
  8. }
复制代码
四、关于端标语和地址

windows操纵系统下,可以通过cmd举行IP地址和端标语的查询
IP地址查询:ipconfig
一般利用IPV4右侧的IP地址
端标语查询:netstat -na
TCP对应的端标语,此中LISTENING代表监听状态,ESTABLISHED代表已毗连,TIME_WAIT代表结束访问,CLOSE_WAIT代表等候制止。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表