Qt学习之路-2(udp/网络聊天室/文件传输)

作者在 2015-08-30 11:25:43 发布以下内容

本文有很多c语言代码,客户端是在qt上完成,里面涉及的socket编程大多都是c构建的。因为我也是初学者,对于初学者很容易理解。至于服务端完全有c代码写成直接可以运行,当然还涉及到简单数据库(mysql)。

网络聊天室:

简介:基于Qt界面,和网络协议UdpMysql数据库,实现用户的注册与登录,和消息的收发,文件的传输。

1. MYsql数据库的建立(用于存储用户名,和密码)。

2.服务器的搭建:采用UDP传输控制协议,实现对不同种类的消息(如注册,登录,聊天,退出),分类处理。对登录和注册信息,与数据库建立连接,实时查找,和插入数据。用多线程处理,收发消息的同步。多客户时,对客服端的消息对每个客服端进行广播实现多人聊天。

3.客服端的搭建:用Qt搭建,图形界面的工程,多层窗口。对各种消息的种

类进行分类。处理图形界面获取的文本信息,通过网络发给服务器,显示服务器转发多人聊天信息。

4. 在聊天主窗口上安置文件传输按钮,绑定信号与槽函数。发送端获取本地文件路径和文件名,文件名传输采用UDP广播来实现。当收到客服端同意接收的信号后,服务器端对文件进行读操作,存入缓存区通过TCP发送给指定地址。当有消息到客户端时触发槽函数,读入缓存区,写进文件,文件传输完成。

5.进行多人聊天,和文件传输。

登录主界面:

log.png (上传于2015-08-30 11:25:43)
log.png

注册界面:

regi.png (上传于2015-08-30 11:25:43)
regi.png

聊天主界面:

chat2.png (上传于2015-08-30 11:25:43)
chat2.png

文件收发界面:

Qt-1

dialog.h

#ifndef DIALOG_H
#define DIALOG_H
#include<QLineEdit>
#include <QDialog>
#include<QUdpSocket>
#include<QtNetwork>
#include"thread.h"
typedef struct
{
    char type;
    char name[32];
    char ps[20];
    char text[256];
}MSG;
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    QUdpSocket *sender; //sender = new QUdpSocket(this);
    QHostAddress serverAddress ;//= QHostAddress("127.0.0.1");
    QTimer *timer;
    Thread *a;
private slots:
    void connected();
    void getIp();
    void gettime();
    void  recvmessage(char *b);
    void reg();
private:
    Ui::Dialog *ui;
signals:
    void qu();
};

#endif // DIALOG_H
dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include<QString>
#include"form.h"
#include<QLineEdit>
#include<QByteArray>
#include<QMessageBox>
#include<QDateTime>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include"widget.h"
#include <server.h>
#include <client.h>
MSG tmp;
MSG msg;
int socked;
socklen_t addr_len;
struct sockaddr_in server_addr;

Dialog::Dialog(QWidget *parent) : QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    this->setWindowTitle (tr("网络聊天室"));
    if((socked=socket (AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0)
    {
        perror("socked:");
        exit(1);
    }
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.71.115");
    server_addr.sin_port = htons(8888);
    addr_len = sizeof(server_addr);
    timer = new QTimer(this);
    connect((QObject*)timer, SIGNAL(timeout()), this, SLOT(gettime()));
    timer->start(1000);
    a=new Thread;
    a->flag=1;
    a->start ();
    connect (a,SIGNAL(ok(char*)),this,SLOT(recvmessage(char*)));
    connect (this,SIGNAL(qu()),a,SLOT(quit()));
    getIp();
    gettime ();

}

Dialog::~Dialog()
{
    delete ui;
}
void Dialog::connected ()
{

    QString f=ui->lineEdit->text ();
    QString b=ui->lineEdit_2->text ();
    QByteArray c=f.toLatin1 ();
    QByteArray d=b.toLatin1 ();
    char *ch=c.data ();
    char *ca=d.data ();
    memcpy(msg.name,ch,c.length ());
    msg.name[c.length ()] = 0;
    memcpy(msg.ps,ca,d.length ());
    msg.ps[d.length ()] = 0;
    msg.type='L';
    memset(msg.text,0,sizeof(msg.text));
    QMessageBox box;
    box.setWindowTitle (tr("错误"));
    if(f.length()==0)
    {
        box.setText(tr("请输入用户名"));
        box.exec();
    }
    else if(b.length()==0)
    {
        box.setText(tr("请输入密码"));
        box.exec();
    }
    if(sendto(socked,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
    {
        perror("sendto3");
        exit(-1);
    }
    ui->lineEdit->clear ();
    ui->lineEdit_2->clear ();

}
void Dialog::recvmessage (char *b)
{

    if(memcmp(((MSG*)b)->text,"hello",5)==0)
    {
        QMessageBox box;
        box.setWindowTitle (tr("错误"));
        box.setText(tr("帐号或密码错误"));
        box.exec();
        return;
    }
    else
    {  
        a->flag=0;
        tmp=msg;
        emit qu();
        a->disconnect (this,SLOT(recvmessage(char*)));
        this->close ();
        Form *test = new Form;
        test->show();
    }

}
void Dialog::reg ()
{
     MSG b;
    b.type='A';
    sendto(socked,&b,sizeof(b),0,(struct sockaddr*)&server_addr,addr_len);
    a->flag=0;
    a->disconnect (this,SLOT(recvmessage(char*)));
    emit qu();  
    this->close ();
    Widget *test = new Widget;
    test->show();
}
void Dialog::getIp()
{
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
        if(address.protocol() == QAbstractSocket::IPv4Protocol)   //我们使用IPv4地址
        {
            if(address.toString().contains("192.168.1")||address.toString().contains("127.0"))
                continue;
            //qDebug()<<"本机Ip:"<<address.toString();
            //return address.toString();
            ui->label_4->setText ("本机IP:"+address.toString ());
        }
    }
    //return 0;
}
void Dialog::gettime ()
{
    QDateTime time;
    QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
    QByteArray a=timeStr.toLocal8Bit ();
    ui->label_5->setText(a);
}



from.h

#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include<QLineEdit>
#include <QDialog>
#include<QUdpSocket>
#include<QtNetwork>
#include"thread.h"
namespace Ui {
class Form;
}

class Form : public QWidget
{
    Q_OBJECT

public:
    explicit Form(QWidget *parent = 0);
    ~Form();
    QUdpSocket *sender; //sender = new QUdpSocket(this);
    QHostAddress serverAddress ;//= QHostAddress("127.0.0.1");
    QTimer *timer;
    Thread *b;
    void closeEvent (QCloseEvent *);
private slots:
    void  sendmessage();
    void  recvmessage(char *a);
    void  cleansend();
    void  getIp();
    void  gettime();
    void autoScroll();
    void on_SendFile_clicked();


    void on_recevFile_clicked();

public:
    Ui::Form *ui;
};


#endif // FORM_H

from.cpp

#include "form.h"
#include "ui_form.h"
#include<QTextCodec>
#include<QTextEdit>
#include"dialog.h"
#include<QMessageBox>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<QTimer>
#include"thread.h"
#include <server.h>
#include <client.h>


Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form)
{  
    //QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
    ui->setupUi(this);
    timer = new QTimer(this);
    connect((QObject*)timer, SIGNAL(timeout()), this, SLOT(gettime()));
    timer->start(1000);
    getIp ();
    b=new Thread;
    connect (b,SIGNAL(ok(char*)),this,SLOT(recvmessage(char *)));
    b->flag=1;
    b->start ();


}
void Form::sendmessage ()
{
    autoScroll();
    extern MSG msg;
    extern int socked;
    extern struct sockaddr_in server_addr;
    extern socklen_t addr_len;
    //QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
    QString talkMsg = ui->textEdit->toPlainText();
    QByteArray c=talkMsg.toLocal8Bit ();
    char *ch=c.data ();
    memcpy(msg.text,ch,c.length ());
    msg.text[c.length ()] = 0;
    msg.type='B';
    QMessageBox box;
    box.setWindowTitle (tr("错误"));
    if(talkMsg.length()==0)
    {
        box.setText(tr("发送信息不能为空"));
        box.exec();
    }
    else
    {
        if(sendto(socked,&msg,sizeof(msg),0,(struct sockaddr*)&server_addr,addr_len) < 0)
        {
            perror("sendto2");
            exit(-1);
        }
        ui->textEdit->clear ();
        ui->textEdit->setFocus ();

    }

}
void Form::recvmessage (char *a)
{

    switch(((MSG*)a)->type)
    {
    case 'L':
        ui->textBrowser->insertPlainText ("the ");
        ui->textBrowser->insertPlainText (((MSG*)a)->name);
        ui->textBrowser->insertPlainText (" login");
        ui->textBrowser->insertPlainText ("\n");
        autoScroll();
        break;
    case 'B':
        ui->textBrowser->insertPlainText (((MSG*)a)->name);
        ui->textBrowser->insertPlainText (" 说:");
        ui->textBrowser->insertPlainText (((MSG*)a)->text);
        ui->textBrowser->insertPlainText ("\n");
        autoScroll();
        break;
    case 'Q':
        ui->textBrowser->insertPlainText (((MSG*)a)->name);
        ui->textBrowser->insertPlainText (" 退出");
        ui->textBrowser->insertPlainText ("\n");
        autoScroll();
        break;
    }

}
void Form::autoScroll()   //设置滚屏
{
    QTextCursor cursor = ui->textBrowser->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->textBrowser->setTextCursor(cursor);
}
void Form::closeEvent (QCloseEvent *)
{
    extern MSG tmp;
    extern int socked;
    extern struct sockaddr_in server_addr;
    extern socklen_t addr_len;
    tmp.type='Q';
    qDebug ("name:%s",tmp.name);
    if(sendto(socked,&tmp,sizeof(tmp),0,(struct sockaddr*)&server_addr,addr_len) < 0)
    {
        perror("sendto2");
        exit(-1);
    }

    qDebug("close");
}

void Form::getIp()
{
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
        if(address.protocol() == QAbstractSocket::IPv4Protocol)  //我们使用IPv4地址
        {
            if(address.toString().contains("192.168.1")||address.toString().contains("127.0"))
                continue;
            //qDebug()<<"本机Ip:"<<address.toString();
            //return address.toString();
            ui->label->setText ("本机IP:"+address.toString ());
        }
    }
    //return 0;
}
void Form::gettime ()
{
    QDateTime time;
    QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
    QByteArray a=timeStr.toLocal8Bit ();
    ui->label_2->setText(a);
}
void Form::cleansend()
{
    ui->textEdit->clear ();
    ui->textEdit->setFocus ();
}
Form::~Form()
{
    delete ui;
}

void Form::on_SendFile_clicked()
{
    Server *file = new Server;
    file->setWindowTitle("Server");
    file->show();
}

void Form::on_recevFile_clicked()
{
    Client *File = new Client;
    File->setWindowTitle("Client");
    File->show();
}

thread.h

#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <QtGui>
#include <QUdpSocket>
class Thread : public QThread
{
    Q_OBJECT
public:
     Thread();
    ~Thread();
     int flag;
protected:
    void run();
    int exec ();
signals:
    void ok(char *a);
    void qu();

private:
private slots:

};
#endif // THREAD_H

thread.cpp

 #include "thread.h"
#include "dialog.h"
#include <QObject>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include"form.h"
Thread::Thread()
{
   flag=0;
}

void  Thread::run()
{
    qDebug("thread run");
    MSG a;
    extern int socked;
    extern struct sockaddr_in server_addr;
    extern socklen_t addr_len;

    while(flag)
    {
        if(recvfrom(socked,&a,sizeof(a),0,(struct sockaddr*)&server_addr,&addr_len) < 0)
        {
            perror("recvfrom");
            exit(-1);
        }
       emit ok((char *)&a);
       qDebug ("the data is coming");
       qDebug ("rev1111:%s",a.text);
       this->sleep (1);
    }

}
Thread::~Thread ()
{

    qDebug ("quit\n");


}


文件收发代码在上一博客,本文不再累赘.

服务代码及检测包:



默认分类 | 阅读 18645 次
文章评论,共0条
游客请输入验证码
浏览107799次
文章分类
最新评论