QT TCP编程
QTcpServer QTcpSocket
《案例》网络聊天室(局域网)
① 服务器
1 )使用QTcpServer创建并发服务器
2 )保存所有客户端的socket套接字
3 )接收客户端的消息
4 )转发消息给所有的客户端
工程名:Server
类名:TcpServer
QTcpServer QTcpSocket
《案例》网络聊天室(局域网)
① 服务器
1 )使用QTcpServer创建并发服务器
2 )保存所有客户端的socket套接字
3 )接收客户端的消息
4 )转发消息给所有的客户端
工程名:Server
类名:TcpServer
② 客户端
1 )使用QTcpSocket创建tcp客户端
2 )连接到指定的服务器
3 )发送消息到服务器
4 )接收聊天消息并显示
工程名:Client
类名:TcpClient
/* 客户端 - 代码演示 */
// logindialog.h
#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H
#include <QDialog>
namespace Ui {
class LoginDialog;
}
class LoginDialog : public QDialog
{
Q_OBJECT
public:
explicit LoginDialog(QWidget *parent = 0);
~LoginDialog();
private slots:
void on_pushButton_clicked();
private:
Ui::LoginDialog *ui;
};
#endif // LOGINDIALOG_H
// logindialog.cpp
#include "logindialog.h"
#include "ui_logindialog.h"
LoginDialog::LoginDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::LoginDialog)
{
ui->setupUi(this);
}
LoginDialog::~LoginDialog()
{
delete ui;
}
void LoginDialog::on_pushButton_clicked()
{
qDebug("登录成功!");
close();
}
// TcpClient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QDialog>
#include <QHostAddress>
#include <QTcpSocket>
namespace Ui {
class TcpClient;
}
class TcpClient : public QDialog
{
Q_OBJECT
public:
explicit TcpClient(QWidget *parent = 0);
~TcpClient();
private slots:
//发生消息按钮槽函数
void on_sendButton_clicked();
//连接服务器按钮槽函数
void on_connectButton_clicked();
//和服务器建立连接槽函数
void onConnected();
//和服务器断开连接槽函数
void onDisconnected();
//接收服务器消息的槽函数
void slotDataRecived();
private:
Ui::TcpClient *ui;
//标记客户端连接状态 ture->在线 flase->离线
bool status;
QTcpSocket tcpSocket;
quint16 port;//服务器端口
QHostAddress serverIp;//服务器的IP
QString userName;//聊天昵称
};
#endif // TCPCLIENT_H
// TcpClient.cpp
#include "TcpClient.h"
#include "ui_TcpClient.h"
TcpClient::TcpClient(QWidget *parent) :
QDialog(parent),
ui(new Ui::TcpClient)
{
ui->setupUi(this);
status = false;//初始化连接状态:离线
//和服务器连接是发送信号connected()
connect(&tcpSocket,SIGNAL(connected()),
this,SLOT(onConnected()));
//和服务器断开连接是发送信号disconnected()
connect(&tcpSocket,SIGNAL(disconnected()),
this,SLOT(onDisconnected()));
//套接字有数据到来是发送信号readyRead
connect(&tcpSocket,SIGNAL(readyRead()),
this,SLOT(slotDataRecived()));
}
TcpClient::~TcpClient( )
{
delete ui;
}
//发送消息按钮的槽函数
void TcpClient::on_sendButton_clicked()
{
//获取用户输入的消息
QString msg = ui->sendEdit->text();
if( msg == ""){
return;
}
msg = userName + ":" + msg;
//发送消息
tcpSocket.write(msg.toLocal8Bit());
//清空输入组件
ui->sendEdit->clear();
}
void TcpClient::on_connectButton_clicked()
{
//如果当前是离线状态则连接服务器
if(status == false){
status = true;
//获取服务器IP
serverIp.setAddress(ui->serverIpEdit->text());
//获取聊天昵称
userName = ui->userEdit->text();
//获取服务器端口
port = ui->portEdit->text().toShort();
//向服务器发送连接请求
tcpSocket.connectToHost(serverIp,port);
}
else{ //如果当前是在线状态则断开连接
//发送下线消息
QString msg = userName + ":离开聊天室";
tcpSocket.write(msg.toLocal8Bit());
//断开和服务器的连接
tcpSocket.disconnectFromHost();
status = false;
}
}
//和服务器建立连接槽函数
void TcpClient::onConnected()
{
//使能发送消息按钮
ui->sendButton->setEnabled(true);
//"连接服务器" 内容改为 "离开聊天室"
ui->connectButton->setText("离开聊天室");
//禁用输入组件
ui->serverIpEdit->setEnabled(false);
ui->portEdit->setEnabled(false);
ui->userEdit->setEnabled(false);
//发送上线消息
QString msg = userName + ":进入聊天室";
tcpSocket.write(msg.toLocal8Bit());
}
//和服务器断开连接槽函数
void TcpClient::onDisconnected()
{
//禁用发送消息按钮
ui->sendButton->setEnabled(false);
//使能输入组件
ui->serverIpEdit->setEnabled(true);
ui->portEdit->setEnabled(true);
ui->userEdit->setEnabled(true);
// "离开聊天室" 内容改为 "连接服务器"
ui->connectButton->setText("连接服务器");
}
//接收服务器消息的槽函数
void TcpClient::slotDataRecived()
{
if(tcpSocket.bytesAvailable()){
QByteArray datagram;
datagram.resize(tcpSocket.bytesAvailable());
//读取消息
tcpSocket.read(datagram.data(),datagram.size());
//显示到ui
ui->listWidget->addItem(datagram);
}
}
// main.cpp
#include "TcpClient.h"
#include "logindialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
LoginDialog login;
login.show();
login.exec();
TcpClient w;
w.show();
return a.exec();
}
/* 服务器端 - 代码演示 */
// TcpServer.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QDialog>
#include <QTcpServer>
#include <QTcpSocket>
namespace Ui {
class TcpServer;
}
class TcpServer : public QDialog
{
Q_OBJECT
public:
explicit TcpServer(QWidget *parent = 0);
~TcpServer();
private slots:
//创建按钮信号对应的操函数
void on_createButton_clicked();
//客户端和服务器建立连接时,发送信号newConection
void onNewConnection(void);
//接收客户端数据的槽函数
void slotDataReceived(void);
private:
//转发消息到所有的客户端
void sendMessage(const QByteArray&);
private:
Ui::TcpServer *ui;
QTcpServer tcpServer;//服务器对象
quint16 port;//服务器端口
//容器:保存所有和客户端通信的socket
QList <QTcpSocket*> tcpClientList;
};
#endif // TCPSERVER_H
// TcpServer.cpp
#include "TcpServer.h"
#include "ui_TcpServer.h"
TcpServer::TcpServer(QWidget *parent) :
QDialog(parent),
ui(new Ui::TcpServer)
{
ui->setupUi(this);
connect(&tcpServer,SIGNAL(newConnection()),
this,SLOT(onNewConnection()));
}
TcpServer::~TcpServer()
{
delete ui;
}
//创建服务器
void TcpServer::on_createButton_clicked()
{
//获取端口号
port = ui->portEdit->text().toShort();
//开启服务器
tcpServer.listen(QHostAddress::Any,port);
//禁用创建服务器按钮和端口输入
ui->createButton->setEnabled(false);
ui->portEdit->setEnabled(false);
}
//客户端和服务器建立连接时,发送信号newConection
void TcpServer::onNewConnection(void)
{
//获取和客户端通信的tcp套接子
QTcpSocket* tcpClient =
tcpServer.nextPendingConnection();
//保存当前套接子到容器
tcpClientList.append(tcpClient);
//当客户端给服务器发送消息时,发送信号readyRead
connect(tcpClient,SIGNAL(readyRead()),
this,SLOT(slotDataReceived()));
}
//接收客户端数据的槽函数
void TcpServer::slotDataReceived(void)
{
//遍历所有客户端
for(int i=0; i<tcpClientList.count(); i++){
//检查当前客户端套接子是否有数据到来
if(tcpClientList.at(i)->bytesAvailable()){
//读取消息
QByteArray readbuf =
tcpClientList.at(i)->readAll();
//显示消息到服务器Ui
ui->listWidget->addItem(readbuf);
//转发消息给所有的客户端
sendMessage(readbuf);
}
}
}
//转发消息到所有的客户端
void TcpServer::sendMessage(const QByteArray& msg)
{
for(int i=0; i<tcpClientList.count(); i++){
tcpClientList.at(i)->write(msg);
}
}
// main.cpp
#include "TcpServer.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TcpServer w;
w.show();
return a.exec();
}