Qt5.14.2开发平台可以开发桌面应用,适配Linux,windows,Mac,使用
C++
编写,学习一下,用个demo练手,服务端是用
Java
编写Netty框架,客户端使用Qt开发。
Netty的pom引用:
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.77.Final</version>
</dependency>
Java服务端代码:
package com.my.chatroom;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class ChatServer {
public static void main(String[] args) {
ChatServer server=new ChatServer(9996);
server.run();
}
private int port;
public ChatServer(int port) {
this.port = port;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void run() {
EventLoopGroup bossGroup=new NioEventLoopGroup();
EventLoopGroup workerGroup=new NioEventLoopGroup();
ServerBootstrap serverBootstrap=new ServerBootstrap();
try {
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline=ch.pipeline();
/*
* 网络数据都是二进制数据,但是业务数据一般都不是二进制数据,
* 这时就需要将业务数据转换为二进制,接收的二进制再转换为业务需要的数据
* 业务端String进入网络,成为二进制数据,StringDecoder将二进制转换为字符串
* 业务处理后,StringEncoder将字符串转换为二进制传输出去
*/
//往pipeline链中添加解码器
pipeline.addLast("decoder",new StringDecoder());
//往pipeline链中添加编码器
pipeline.addLast("encoder",new StringEncoder());
//将业务将入pipeline链,解码器和编码器一定要在业务类之前。
pipeline.addLast(new ChatServerHandler());
}
});
System.out.println("服务器端已就绪");
ChannelFuture future=serverBootstrap.bind(port);
future.sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
Java客户端代码:
package com.my.chatroom;
import java.util.Scanner;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class ChatClient {
public static void main(String[] args) {
ChatClient client=new ChatClient("127.0.0.1", 9996);
client.run();
}
private String IP;
private int port;
public String getIP() {
return IP;
}
public void setIP(String iP) {
IP = iP;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public ChatClient(String iP, int port) {
IP = iP;
this.port = port;
}
public void run() {
EventLoopGroup group=new NioEventLoopGroup();
try {
Bootstrap bootstrap=new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline=ch.pipeline();
//解码
pipeline.addLast("decoder",new StringDecoder());
//编码
pipeline.addLast("encoder",new StringEncoder());
//业务处理类
pipeline.addLast(new ChatClientHandler());
}
});
ChannelFuture future=bootstrap.connect(IP, port);
future.sync();
Channel channel=future.channel();
Scanner scanner=new Scanner(System.in);
while(scanner.hasNext()) {
String text=scanner.nextLine();
channel.writeAndFlush(text+"\n\r");
}
channel.closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
group.shutdownGracefully();
}
}
}
Qt 平台C++代码:MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QColorDialog>
#include <QDebug>
#include <QErrorMessage>
#include <QHostAddress>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
m_tcp = new QTcpSocket;
m_tcp->connectToHost(QHostAddress("10.60.1.117"),9996);
setWindowTitle("OO");
ui->setupUi(this);
connect(m_tcp,&QTcpSocket::readyRead,this,[=]()
{
QByteArray data = m_tcp->readAll();
ui->record->appendPlainText("服务器说:"+data);
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString s = ui->msg->toPlainText();
qDebug()<<"str=="<<s;
ui->record->appendPlainText("客户端说:"+s);
m_tcp->write(s.toUtf8());
ui->msg->clear();
}
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QErrorMessage>
#include <QLabel>
#include <QMainWindow>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
private:
QErrorMessage *error;
QTcpSocket *m_tcp;
QLabel *m_status;
};
#endif // MAINWINDOW_H
C++工程的 .pro文件,必须加入QT += network,才能使用TCP通信模块
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
QT += network
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
ui各位随意,本人画的比较朴素,哈哈!
C++本项目源码免费下载:
基于QtCreator5.12.4C++客户端-C++文档类资源-CSDN下载
带图标版,打包后带有图标:
Qtcreator5.9.9聊天客户端软件,带图标-C++文档类资源-CSDN下载
下面看看运行效果:
首先运行Java的Netty服务端,后运行Qt桌面应用客户端
查看服务端输出
启动Java的Netty客户端
Qt 客户端发送消息:
查看Netty服务端和客户端消息输出
Java客户端输入发送:
Qt 客户端接收消息并显示:
Java的Netty服务端日志:
打包部署的时候要注意工程编译时使用的编译器要和打包编译器要对应,不然会出问题。
带图标的exe生成后:海绵宝宝的ico
发个表情,竟然是黑白的,哈哈,待优化