Qt学习之基于tcp的简单网络聊天室

QListWidget类提供了一个基于item的列表小部件。QListWidget是一个方便的类,它提供了类似于QlistView所具有的列表视图,但是具有增加和删除的功能。QListWidget使用内部模型来管理列表中的每个QListWidgetItem。想要有更灵活的列表视图,请使用具有标准模型的QListView类。
服务器端代码

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QPushButton>
#include<QLabel>
#include<QTextEdit>
#include<QLineEdit>
#include<QGridLayout>
#include<QListWidget>
#include"serverh.h"
class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();
private:
    QPushButton *CreatButton;
    QGridLayout *mainLayout;
    QLineEdit *PortLineEdit;
    QListWidget *listwidget;
    QLabel *PortLabel;
private:
    int port;
    serverh *server;
public slots:
    void slotCreatServer();
    void slotupdateServer(QString,int);


};

#endif // DIALOG_H
#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    listwidget=new QListWidget;
    setWindowTitle(tr("tcp Server"));
    PortLabel =new QLabel(QStringLiteral("端口:"),this);
    PortLineEdit=new QLineEdit(this);
    CreatButton=new QPushButton(this);
    CreatButton->setText(QStringLiteral("创建聊天室"));
    mainLayout=new QGridLayout(this);
    mainLayout->addWidget(listwidget,0,0,1,2);
    mainLayout->addWidget(PortLabel,1,0);
    mainLayout->addWidget(PortLineEdit,1,1);
    mainLayout->addWidget(CreatButton,2,0,1,2);
    port=8010;
    PortLineEdit->setText(QString::number(port));
    connect(CreatButton,&QPushButton::clicked,this,&Dialog::slotCreatServer);

}

Dialog::~Dialog()
{

}

void Dialog::slotCreatServer()
{
    server=new serverh(this,port);
    connect(server,&serverh::updateServer,this,&Dialog::slotupdateServer);
    CreatButton->setEnabled(false);
}

void Dialog::slotupdateServer(QString msg, int length)//用于更新服务器上的信息显示
{
   listwidget->addItem(msg.left(length));//从左开始数length长度
}
#ifndef SERVERH_H
#define SERVERH_H
#include<QtNetwork/QTcpServer>
#include<QObject>
#include"tcpclicentsocket.h"


class serverh:public QTcpServer
{
    Q_OBJECT
public:
    serverh(QObject *parent=0,int port=0);
    QList<tcpclicentsocket*> tcpClicentSocketList;
signals:
    void updateServer(QString,int);
public slots:
    void updateClicents(QString,int);
    void slotDisconnected(int);
protected:
    void incomingConnection(int socketDescriptor);

};

#endif // SERVERH_H
#include "serverh.h"
serverh::serverh(QObject *parent,int port)
{
    listen(QHostAddress::Any,port);//在指定的端口对任意地址监听,Any表示ipv4的任意地址

}

void serverh::updateClicents(QString msg, int length)//将任意客户端发来的信息进行广播
{
    emit updateServer(msg,length);
    for(int i=0;i<tcpClicentSocketList.count();i++)
    {
        QTcpSocket *item=tcpClicentSocketList.at(i);
        if(item->write(msg.toLatin1(),length)!=length)
        {
            continue;
        }
    }
}

void serverh::slotDisconnected(int descriptor)
{
    for(int i=0;i<tcpClicentSocketList.count();i++)
    {
        QTcpSocket *item=tcpClicentSocketList.at(i);
        if(item->socketDescriptor()==descriptor)
        {
            tcpClicentSocketList.removeAt(i);//断开这个客户端
            return;
        }
    }
}

void serverh::incomingConnection(int socketDescriptor)
{
    tcpclicentsocket *tcpClicentSocket=new tcpclicentsocket(this);
    //创建一个新的tcpclientsocket来与客户端通信
    connect(tcpClicentSocket,&tcpclicentsocket::updateClicent,this,&serverh::updateClicents);
    connect(tcpClicentSocket,&tcpclicentsocket::disconnected,this,&serverh::slotDisconnected);
    tcpClicentSocket->setSocketDescriptor(socketDescriptor);//指定了连接的socket描述符
    tcpClicentSocketList.append(tcpClicentSocket);//加入链表中方便管理
}
#ifndef TCPCLICENTSOCKET_H
#define TCPCLICENTSOCKET_H
#include<QtNetwork/QTcpSocket>
#include<QObject>

class tcpclicentsocket:public QTcpSocket
{
    Q_OBJECT
public:
    tcpclicentsocket(QObject *parent);
signals:
    void updateClicent(QString,int);//通知服务器想聊天室内的所有的成员广播信息
    void disconnected(int);
protected slots:
    void dataReceived();
    void slotDisconnected();


};

#endif // TCPCLICENTSOCKET_H
#include "tcpclicentsocket.h"

tcpclicentsocket::tcpclicentsocket(QObject *parent)
{
connect(this,&tcpclicentsocket::readyRead,this,&tcpclicentsocket::dataReceived);
connect(this,&tcpclicentsocket::disconnected,this,&tcpclicentsocket::slotDisconnected);
}

void tcpclicentsocket::dataReceived()//将套接字中的有效数据读出
{
    while(bytesAvailable()>0)
    {
        int length=bytesAvailable();//获得数据的大小
        char buf[1024];
        read(buf,length);
        QString msg=buf;
        emit updateClicent(msg,length);
    }

}

void tcpclicentsocket::slotDisconnected()
{
    emit disconnected(this->socketDescriptor());
}

客户端代码

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QListWidget>
#include<QLineEdit>
#include<QPushButton>
#include<QLabel>
#include<QGridLayout>
#include<QHostAddress>
#include<QTcpSocket>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();
private:
    QListWidget *listwidget;
    QPushButton *sendButton;
    QPushButton *enterButton;
    QLineEdit *sendLineEdit;
    QLabel *UsernameLabel;
    QLineEdit* UserLineEdit;
    QLabel *ServerLabel;
    QLineEdit *ServerLineEdit;
    QLabel *portLabel;
    QLineEdit *portLineEdit;
    QGridLayout *mainLayout;
private:
    int port;
    bool status;
    QHostAddress *serverIp;
    QString username;
    QTcpSocket *tcpsocket;
public slots:
    void slotEnter();
    void slotConnected();
    void slotDisconnected();
    void dataReceived();
    void slotSend();

};

#endif // DIALOG_H
#include "dialog.h"
#include<QMessageBox>
#include<QHostInfo>
Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    setWindowTitle(tr("Tcp slicent"));
    listwidget=new QListWidget;
    sendLineEdit=new QLineEdit(this);
    sendButton=new QPushButton(this);
    sendButton->setText(QStringLiteral("发送"));
    UsernameLabel=new QLabel(this);
    UsernameLabel->setText(QStringLiteral("用户名"));
    UserLineEdit=new QLineEdit(this);
    ServerLabel=new QLabel(this);
    ServerLabel->setText(QStringLiteral("服务器地址"));
    ServerLineEdit=new QLineEdit(this);
    portLabel=new QLabel(tr("端口"),this);
    portLineEdit=new QLineEdit(this);
    enterButton=new QPushButton(this);
    enterButton->setText(QStringLiteral("进入聊天室"));
    mainLayout=new QGridLayout(this);
    mainLayout->addWidget(listwidget,0,0,1,2);
    mainLayout->addWidget(sendLineEdit,1,0);
    mainLayout->addWidget(sendButton,1,1);
    mainLayout->addWidget(UsernameLabel,2,0);
    mainLayout->addWidget(UserLineEdit,2,1);
    mainLayout->addWidget(ServerLabel,3,0);
    mainLayout->addWidget(ServerLineEdit,3,1);
    mainLayout->addWidget(portLabel,4,0);
    mainLayout->addWidget(portLineEdit,4,1);
    mainLayout->addWidget(enterButton,5,0,2,1);
    status=false;
    port=8010;
    portLineEdit->setText(QString::number(port));
    serverIp=new QHostAddress();
    connect(enterButton,&QPushButton::clicked,this,&Dialog::slotEnter);
    connect(sendButton,&QPushButton::clicked,this,&Dialog::slotSend);
    sendButton->setEnabled(false);

}

Dialog::~Dialog()
{

}

void Dialog::slotEnter()
{
    if(!status)
    {
        QString ip=ServerLineEdit->text();
        if(!serverIp->setAddress(ip))
        {
            QMessageBox::information(this,tr("error"),tr("server ip is error"));
            return;
        }

    if(UserLineEdit->text()=="")
    {
        QMessageBox::information(this,tr("error"),tr("user name error"));
        return;
    }
    username=UserLineEdit->text();
    tcpsocket=new QTcpSocket(this);
    connect(tcpsocket,&QTcpSocket::connected,this,&Dialog::slotConnected);
    connect(tcpsocket,&QTcpSocket::disconnected,this,&Dialog::slotDisconnected);
    connect(tcpsocket,&QTcpSocket::readyRead,this,&Dialog::dataReceived);
    tcpsocket->connectToHost(*serverIp,port);
    status=true;
    }
    else {

        int length=0;
        QString msg=username+tr("leave chat room");//构造一条离开聊天室的信息
        if((length=tcpsocket->write(msg.toLatin1(),msg.length()))!=msg.length())
        {
            return;
        }
        tcpsocket->disconnectFromHost();//与服务器断开连接
        status=false;
    }
}

void Dialog::slotConnected()
{
    sendButton->setEnabled(true);
    enterButton->setText(tr("离开"));
    int length=0;
    QString msg=username+tr("enter chat room");
    if((length=tcpsocket->write(msg.toLatin1(),msg.length()))!=msg.length())
    {
        return;
    }

}

void Dialog::slotDisconnected()
{
    sendButton->setEnabled(false);
    enterButton->setText(tr("进入聊天室"));

}

void Dialog::dataReceived()
{
    while(tcpsocket->bytesAvailable()>0)
    {
        QByteArray datagram;
        datagram.resize(tcpsocket->bytesAvailable());
        tcpsocket->read(datagram.data(),datagram.size());
        QString msg=datagram.data();
         listwidget->addItem(msg.left(datagram.size()));

    }
}

void Dialog::slotSend()
{
    if(sendLineEdit->text()=="")
    {
        return;
    }
    QString msg=sendLineEdit->text();
    tcpsocket->write(msg.toLatin1(),msg.length());
    sendLineEdit->clear();//删除已经输入的内容

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值