一、媒介
Qt框架提供了QTcpServe和QTcpSocket两种类实现TCP协议的相关毗连,TCP协议不再过多赘述,以下主要讲述自机服务器和自机客户端的毗连实现TCP协议通讯的详细方式。
二、根本功能介绍
利用Qt网络模块之前必要在.pro文件种加入network
服务器端
绑定端口,并通过信号判断新连入客户机,同时输出相关内容,同时通过断连信号举行客户端的删除。
收信功能绑定读取信号槽函数,对所带数据举行读取显示。
发信功能找到对应的客户机地址和端口举行发信
客户机端
毗连端口
收信功能绑定读取信号槽函数
发信功能直接将发送数据写入设备
三、详细原理和代码实现
在.pro文件中加入network
初始化并分配指针空间
- void Widget::Init()
- {
- myClient = new QTcpSocket(this);
- }
复制代码
服务器端实现
1.ui设计
搭建IP地址框和端口框Line Edit,信息吸取框和发送框Tetx Edit,两个PushButton举行绑定和发送
2.IP绑定
通过listen方法指示服务器侦听地址、地址和端口端口上的传入毗连。如果端口为 0,则自动选择端口。如果 address 为 QHostAddress::Any,则服务器将侦听所有网络接口。
setEnable设置按钮是否可以利用
setMaxPendingConnection设置最大挂起客户机数量
- void Widget::on_btn_bind_clicked()
- {
- QString myAddr;
- //手动设置ip
- myAddr = ui->ledit_serv_addr->text();
- QString myPort = ui->ledit_serv_port->text();
- QString msg;
- bool ret = myServer->listen(QHostAddress(myAddr),myPort.toUInt());
- if(!ret)
- {
- msg = "绑定失败";
- }
- else
- {
- msg = "绑定成功";
- ui->btn_bind->setEnabled(false);
- }
- ui->textEdit->append(msg);
- myServer->setMaxPendingConnections(MAXNUM);
- connect(myServer,SIGNAL(newConnection()),this,SLOT(doProcessNewConnection()));
- connect(myServer,SIGNAL(acceptError(QAbstractSocket::SocketError)),
- this,SLOT(doProcessAcceptError(QAbstractSocket::SocketError)));
- }
复制代码 3.客户端连入
nextPendingConnection(),用于等候并担当下一个挂起的毗连。当一个客户端请求毗连时,服务器会将该毗连挂起,等候服务器担当毗连。nextPendingConnection()函数会阻塞当前线程,直到有一个毗连被担当。一旦有毗连被担当,会返回一个QTcpSocket对象。
此时对客户端的IP地址和端标语举行读取并显示
- void Widget::doProcessNewConnection()
- {
- client = myServer->nextPendingConnection();
- arrayClient.append(client);
- QString msg = QString("客户端[%1:%2] 连入!")
- .arg(client->peerAddress().toString())
- .arg(client->peerPort());
- ui->textEdit->append(msg);
- //客户端断开
- connect(client,SIGNAL(diconnected()),this,SLOT(doProcessDiconnected()));
- //读取内容
- connect(client,SIGNAL(readyRead()),this,SLOT(doProcessReadyRead()));
- }
复制代码 4.客户端退出
当客户端退出时,通过sender返回指向发送信号的对象的指针,同时遍历客户机列表删除对应的客户端
- void Widget::doProcessDiconnected()
- {
- QTcpSocket *client = (QTcpSocket *)this->sender();
- QString msg = QString("客户端[%1:%2] 退出!")
- .arg(client->peerAddress().toString())
- .arg(client->peerPort());
- ui->textEdit->append(msg);
- //删除对应客户端
- for(int i= 0;i<arrayClient.length();i++)
- {
- if(arrayClient.at(i)->peerAddress() == client->peerAddress())
- {
- if(arrayClient.at(i)->peerPort() == client->peerPort())
- {
- arrayClient.removeAt(i);
- break;
- }
- }
- }
- }
复制代码 5.吸取信息
利用readyRead()信号,每当有新数据可用于从器件的当前读取通道读取时,该信号就会发出一次。将该信号内容举行循环读取并举行显示。
- void Widget::doProcessReadyRead()
- {
- 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->textEdit->append(str2);
- }
复制代码 6.发送信息
读取输入的客户端IP和端口信息,遍历客户端列表,找到对应的客户端通过write举行数据写入。
- void Widget::on_btn_send_clicked()
- {
- QString ip = ui->ledit_client_ip->text();
- QString port = ui->ledit_client_port->text();
- //查找对应的客户
- for(int i=0;i<arrayClient.length();i++)
- {
- if(arrayClient.at(i)->peerAddress().toString()==ip)
- {
- if(arrayClient.at(i)->peerPort() == port.toUInt())
- {
- QString msg = ui->textEdit_2->toPlainText();\
- arrayClient.at(i)->write(msg.toUtf8());
- ui->textEdit_2->clear();
- break;
- }
- }
- }
- }
复制代码 客户机端实现
1.ui设计
搭建IP地址框和端口框Line Edit,信息吸取框和发送框Tetx Edit,两个PushButton举行毗连和发送
2.服务器毗连
connectTohost对指定的IP地址和端标语举行毗连,同时绑定四信号和槽函数
- void Widget::on_btn_bind_clicked()
- {
- QString servIp = ui->ledit_serv_addr->text();
- QString servPort = ui->ledit_serv_port->text();
- myClient->connectToHost(QHostAddress(servIp),servPort.toUInt());
- connect(myClient,SIGNAL(connected()),this,SLOT(doProcessConnected()));
- connect(myClient,SIGNAL(readyRead()),this,SLOT(dorProcessReadyRead()));
- connect(myClient,SIGNAL(disconnected()),this,SLOT(doProcessDisconnected()));
- connect(myClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(doProcessError(QAbstractSocket::SocketError)));
- }
复制代码 3.信息吸取
readyRead信号举行读取,与服务器端相同
- void Widget::dorProcessReadyRead()
- {
- QString msg,str1,str2;
- str1 = QString(" 服务器[%1:%2] 说:")
- .arg(myClient->peerAddress().toString())
- .arg(myClient->peerPort());
- while(!myClient->atEnd())
- {
- str2.append(QString(myClient->readAll()));
- }
- msg = QString("%1%2").arg(str1).arg(str2);
- ui->textEdit->append(msg);
- }
复制代码 4.信息发送
write举行写入,与服务器端相同
- void Widget::on_btn_send_clicked()
- {
- QString msg = ui->textEdit_2->toPlainText();
- int ret = myClient->write(msg.toUtf8());
- if(ret<=0)
- return;
- ui->textEdit_2->clear();
- }
复制代码 四、关于端标语和地址
windows操纵系统下,可以通过cmd举行IP地址和端标语的查询
IP地址查询:ipconfig
一般利用IPV4右侧的IP地址
端标语查询:netstat -na
TCP对应的端标语,此中LISTENING代表监听状态,ESTABLISHED代表已毗连,TIME_WAIT代表结束访问,CLOSE_WAIT代表等候制止。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |