嘿嘿我又来了
项目简介
最近年底,总体来说比较空闲,开始倒腾倒腾自己做点项目吧,时间荒废了也不太好,就抽空把之前学习的东西做个总结。现在大家时间都宝贵,我也把程序介绍的尽量简单,方便大家阅读,也方便未来回顾。做完这个项目可以入门linux应用。。。(吹牛的)
这个项目大概是希望做一个类似于QQ一样的东西,服务器是挂在腾讯云上的,然后客户端是用QT做的,客户端可以定义自己的用户名向服务端发起请求,服务端接收后会把客户加入到群聊中,并分出线程单独处理该客户的各种消息和请求。
做了一个相对丑陋的界面,如下图,也是现在的V0.1版本。
中间用到的知识相对来说也比较简单。
服务端:C++,TCP,多线程,Makefile。。。
客户端:QT,TCP。。。
都是一些基础的知识,但是对于新手程序猿练手而言感觉还是不错的项目,比起之前预想的来说遇到的困难还是挺多的,文章的最后我会把程序弄出来,大家可以自行去下载,然后跑一下,我这里也主要是做个记录,避免以后学完就忘记了。这篇文章还是主要介绍下客户端的一些东西。(这段无耻的从上一篇复制了…)
QT
用过QT的都知道,QT有一个很强大的设计工具,可以非常快速的创建一个界面。
1.创建工程
这个不再赘述了,直接上图好吧。
1.新工程→Application→QT Widgets Application
2.工程名
3.一直next,这里这样选就可以了,就完成了。
2.界面设计
1.下面开始设计界面,双击工程里的Mainwindow.ui,会自动跳转到设计界面。
这个过程比较复杂,这些框和按钮都是从右边的工具栏拖出来的,按照一定的排列放起来的。双击按钮可以设置按钮名称。
2.右边属性栏的objectName 一定要重新设置(每一个控件都要),在程序设计时会用到。
3.对于按键,要设置对应的功能,所以右击按键后点击在框里选择click(),就会跳转到程序设计界面,当按键被按下时,程序会跳转到该函数。
3.程序设计
程序设计无非是添加每个按钮的功能。直接上图,解释都在注释里
//关闭按钮
void MainWindow::on_close_btn_clicked()
{
//若未连接则直接关闭程序
if(connected == 0){
}
//若已连接则关闭程序之前先断开连接
else{
QString str = "0";//发送‘0’给服务端表示现在将关闭程序
tcpSocket->write(str.toUtf8().data()); //发送文本框信息
tcpSocket->disconnectFromHost();//TCP断开连接
tcpSocket->close();//TCP关闭
}
//关闭窗口
close();
}
//连接按钮
void MainWindow::on_connect_btn_clicked()
{
//获取服务器的ip和端口
QString ip = ui->lineEditIP->text();//获取输入的IP
qint16 port = ui->lineEditPort->text().toInt();//获取输入的端口号
//若已连接,输出提示信息
if(connected == 1){
ui->connoutput->insertPlainText("You are already logged in.");
ui->connoutput->insertPlainText("\n");
ui->connoutput->moveCursor(QTextCursor::End);
}
//若未连接,连接后输出提示信息
else{
ui->connoutput->insertPlainText("connect with:"+ip);
ui->connoutput->insertPlainText(" port:"+ui->lineEditPort->text());
ui->connoutput->insertPlainText("\n");
ui->connoutput->moveCursor(QTextCursor::End);
//主动和服务器建立连接
tcpSocket->connectToHost(QHostAddress(ip),port);
}
}
//断开连接按钮
void MainWindow::on_quit_btn_clicked()
{
//主动和客户端端口断开连接
QString str = "0";
tcpSocket->write(str.toUtf8().data()); //发送‘0’给服务端表示现在将关闭程序
tcpSocket->disconnectFromHost();//断开连接
connected=0;
//输出提示信息
ui->connoutput->insertPlainText("You have exited from the server.");
ui->connoutput->insertPlainText("\n");
ui->connoutput->moveCursor(QTextCursor::End);
}
//清屏
void MainWindow::on_pushButton_clicked()
{
ui->output->clear();
ui->connoutput->clear();
}
//消息处理函数
void MainWindow::msghandle(QByteArray array){
int i;
//获取时间信息
QDateTime current_date_time =QDateTime::currentDateTime();
QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss");
//数据包格式为“name:message”所以需要获取到‘:’前的name
for(i=0;i<strlen(array);i++){
if(array[i]==':'){
break;
}
}
//获取name,打印时间和名字
QString name = array.mid(0,i);
ui->output->insertPlainText(current_date+" " + name+":");
ui->output->insertPlainText("\n");
//打印消息
ui->output->insertPlainText(array.mid(i+1));
ui->output->insertPlainText("\n");
ui->output->moveCursor(QTextCursor::End);
}
4.网络通讯
网络通讯部分很简单,只需要创建一个成员,在构造函数中初始话即可,使用下面两个连接函数连接一下就OK了。
//在类里创建一个通信套接字和连接标志位
private:
Ui::MainWindow *ui;
QTcpSocket *tcpSocket;//通信套接字
int connected;
//在构造函数里分配一个空间给成员
tcpSocket = new QTcpSocket(this);
//连接成功的连接函数
connect(tcpSocket,&QTcpSocket::connected,[=](){
connected = 1;
ui->connoutput->insertPlainText("connect scceed!");
ui->connoutput->insertPlainText("\n");
QString name = ui->lineEditUser->text();
tcpSocket->write(name.toUtf8().data());
});
//收到消息的信号的连接函数
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
//获取对方发送的内容
QByteArray array = tcpSocket->readAll();
this->msghandle(array);
});
大功告成!
老规矩,贴代码
https://github.com/haishiyoumingtian/TCP_Client.git