效果:
头文件
# ifndefservernetdialog _ h # defineservernetdialog _ h # includeqdialog # includeqtcpserver # includeqtcpsocket # includeqdeqd includeqtcpsocket # incl } classservernetdialog 3360 publicqdialog { q _ object public : explicitservernetdialog q构件* PPP ~serverNetDialog ; private slots: //服务器创建按钮对应的插槽函数void on _ push button _ creatr _ clicked ; //响应来自客户端的连接请求的槽函数void onNewConnection ; //接收客户端消息的槽函数void onReadyRead ; //将聊天消息转发到其他客户端的语音发送消息一致字节顺序); //计时器是无效的连接插槽函数void onTimeOut ); private : ui :3360 servernetdialog * ui; QTCpserverTCP服务器; quint 16端口; //服务器端口qlistqtcpsocket*TCP客户端; //容器:套接字q计时器,用于存储与客户端的所有通信; //计时器,定时检查断开的插座}; #endif //SERVERNETDIALOG_H源文件
# include ‘ servernetdialog.h ‘ # include ‘ ui _ servernetdialog.h ‘ # pragma execution _ character _ set ‘ utf-8 ‘ ) //客户端向服务器发送连接请求信号连接TCP服务器,信号)、新建连接this,slot )、连接onnewconnection ) ); 连接timer,signal ) timeout )、slot on time out ) ); } servernetdialog :3360~servernetdialog ) { delete ui; //服务器创建按钮支持的插槽函数voidservernetdialog :3360 on _ push button _ creatr _ clicked //获取端口号port=ui-line edit _ port 已成功创建服务器IP和端口if设置TCP server.listen qhostaddress 33603360 any,port )==true ) { qDebug )服务器。 ‘; //禁用按钮和输入框ui-push button _ creatr-setenabled false ); ui-line edit _ port-setenabled 假; //计时器timer.start3000 ); } else{ qDebug ) ‘服务器创建失败! ‘; }//响应与客户端连接请求的插槽函数voidservernetdialog : onnewconnection //与客户端通信的套接字qtcpsocket * TCP客户端=TCP server //将套接字保存到容器TCP客户端列表. append TCP客户端)//客户端向服务器发送消息时,通信套接字发送信号: readyreadconnect TCP客户端) slot onreadyread ) )//接收客户端消息的槽函数voidservernetdialog :3360 onreadyread ) forintI=0; I TCP客户端列表. size ; 如果{ //bytesAvailable:获取当前套接字的等待读取的消息字节数,并返回//0,则返回没有消息//0,并且表示消息已到达当前套接字的if TCP客户端列表)
.ati)->bytesAvailable)) { //读取消息并保存 //readAll:读取全部内容 QByteArray buf = tcpClientList.ati)->readAll); //显示聊天消息 ui->listWidget->addItembuf); //最新消息显示在底部 ui->listWidget->scrollToBottom); //转发消息给所有在线客户端 sendMessagebuf); } }}//转发聊天消息给其他客户端void serverNetDialog::sendMessageconst QByteArray& buf){ forint i = 0;i < tcpClientList.size);i++) { tcpClientList.ati)->writebuf); }}//定时器定时删除无效连接套接字槽函数void serverNetDialog::onTimeOut){ //遍历容器中保存的客户端通信套接字是否已经断开连接,如果是则删除 forint i = 0;i < tcpClientList.size);i++) { //state:获取套接字状态,0为断开连接 iftcpClientList.ati)->state) == QAbstractSocket::UnconnectedState) { tcpClientList.removeAti); –i;//将删除的套接字后的个数往前提一个 } }}
ui界面
客户端
头文件
#ifndef CLIENTNETDIALOG_H#define CLIENTNETDIALOG_H#include <QDialog>#include <QTcpSocket>#include <QHostAddress>#include <QMessageBox>#include <QDebug>namespace Ui {class clientNetDialog;}class clientNetDialog : public QDialog{ Q_OBJECTpublic: explicit clientNetDialogQWidget *parent = 0); ~clientNetDialog);private slots: //发送消息槽函数 void on_pushButton_send_clicked); //连接到服务器槽函数 void on_pushButton_connect_clicked); //和服务器连接成功时执行的槽函数 void onConnected); //和服务器断开连接时执行的槽函数 void onDisConnct); //接收聊天消息的槽函数 void onReadyRead); //网络异常时执行的槽函数 void onError);private: Ui::clientNetDialog *ui; bool status;//状态标识:在线/离线 QTcpSocket tcpSocket;//和服务器通信的套接字 QHostAddress serverIP;//服务器ip quint16 serverPort;//服务器端口 QString name;//聊天室昵称};#endif // CLIENTNETDIALOG_H
源文件
#include “clientnetdialog.h”#include “ui_clientnetdialog.h”#pragma execution_character_set”utf-8”)clientNetDialog::clientNetDialogQWidget *parent) : QDialogparent), uinew Ui::clientNetDialog){ ui->setupUithis); status = false;//初始化为离线状态 connect&tcpSocket,SIGNALconnected)),this,SLOTonConnected))); connect&tcpSocket,SIGNALdisconnected)),this,SLOTonDisConnct))); connect&tcpSocket,SIGNALreadyRead)),this,SLOTonReadyRead))); connect&tcpSocket,SIGNALerrorQAbstractSocket::SocketError)),this,SLOTonError)));}clientNetDialog::~clientNetDialog){ delete ui;}//发送消息槽函数void clientNetDialog::on_pushButton_send_clicked){ //获取用户输入聊天消息 QString msg = ui->lineEdit_messge->text); ifmsg == “”){ return; } else{ msg = name + “:” + msg; //发送聊天消息 tcpSocket.writemsg.toUtf8)); //清空消息输入框 ui->lineEdit_messge->clear); }}//连接到服务器槽函数void clientNetDialog::on_pushButton_connect_clicked){ //如果是离线状态,建立和服务器的连接 ifstatus == false){ //获取服务器IP serverIP.setAddressui->lineEdit_ip->text)); //获取服务器端口号 serverPort = ui->lineEdit_port->text).toShort); //获取聊天室名字 name = ui->lineEdit_name->text); //向服务器发送连接请求 //成功:发送信号connect //失败:发送信号error tcpSocket.connectToHostserverIP,serverPort); } //如果是在线状态,断开和服务器的连接 else{ //向服务器发送离开聊天室提示消息 QString msg = name + “:离开聊天室。”; //toUtf8:QString转换成QByteArray tcpSocket.writemsg.toUtf8)); //断开连接,会发送信号:disconnect tcpSocket.disconnectFromHost); }}//和服务器连接成功时执行的槽函数void clientNetDialog::onConnected){ status = true;//在线状态 ui->pushButton_send->setEnabledtrue);//恢复发送消息按钮使能 ui->lineEdit_ip->setEnabledfalse);//禁用IP ui->lineEdit_port->setEnabledfalse);//禁用端口 ui->lineEdit_name->setEnabledfalse);//禁用聊天室昵称 ui->pushButton_connect->setText”离开聊天室”); //向服务器发送进入聊天室提示消息 QString msg = name + “:进入聊天室。”; //toUtf8:QString转换成QByteArray tcpSocket.writemsg.toUtf8));}//和服务器断开连接时执行的槽函数 void clientNetDialog::onDisConnct) { status = false;//在线状态 ui->pushButton_send->setEnabledfalse);//恢复发送消息按钮使能 ui->lineEdit_ip->setEnabledtrue);//禁用IP ui->lineEdit_port->setEnabledtrue);//禁用端口 ui->lineEdit_name->setEnabledtrue);//禁用聊天室昵称 ui->pushButton_connect->setText”连接服务器”); } //接收聊天消息的槽函数 void clientNetDialog::onReadyRead) { iftcpSocket.bytesAvailable)){ //接收消息 QByteArray buf = tcpSocket.readAll); //显示消息 ui->listWidget->addItembuf); ui->listWidget->scrollToBottom); } } //网络异常时执行的槽函数 void clientNetDialog::onError) { //errorString):获取网络异常的原因 QMessageBox::criticalthis,”ERROR”,tcpSocket.errorString)); }
ui界面