自己写的 基于多线程和TCPserver类、TCPsocket的类

来源:互联网 发布:c 生命数组 编辑:程序博客网 时间:2024/06/05 23:54


sever类监听,来一个连接,就开辟一个线程.....还有其他的功能  自己看吧。接口什么的都给了。

#include "tcpseverui.h"#include <QApplication>int main(int argc, char *argv[]){    QApplication a(argc, argv);    TcpSeverUi w;    w.show();    return a.exec();}#ifndef MYDEBUG_H#define MYDEBUG_H    #define MYDEBUG    #ifdef MYDEBUG    #include<QDebug>    #endif#endif // MYDEBUG_H#include "tcpclient.h"#include<QThread>tcpClient::tcpClient(qintptr handle, QObject *parent) :    QTcpSocket(parent),handleback(handle){    connect(this,SIGNAL(disconnected()),this,SLOT(clientDisconnect()));    connect(this,SIGNAL(readyRead()),this,SLOT(getMSg()));    blocksize=0;}tcpClient::~tcpClient(){}void tcpClient::clientDisconnect(){    qDebug()<<"clientDisconnect 套接字"<<handleback;    emit IWantToClose(handleback);}void tcpClient::serverToClientSlots(qintptr handle, const QByteArray &Blocks){    if(handle==handleback)    {        QByteArray send;        QString t=Blocks;        QDataStream out(&send,QIODevice::WriteOnly);        out.setVersion(QDataStream::Qt_5_3);        out<<(quint64)(Blocks.size())<<t;        qDebug()<<"客户线程:"<<QThread::currentThreadId();        qint64 fact=write(send);        emit serverToClientFactByte(fact,handle);    }}void tcpClient::getMSg(){    QString t;    QDataStream in(this);    in.setVersion(QDataStream::Qt_5_3);    in>>blocksize>>t;    clientToServerBlocks.append(t);    qDebug()<<"客户--服务,触发!"<<blocksize;    emit sendForReadMsg(handleback,clientToServerBlocks);}qint64 tcpClient::writeByte(QByteArray Blocks){    QByteArray send;    QString t=Blocks;    QDataStream out(&send,QIODevice::WriteOnly);    out.setVersion(QDataStream::Qt_5_3);    out<<(quint64)(Blocks.size())<<t;    qDebug()<<"客户线程:"<<QThread::currentThreadId();    qint64 fact=write(send);    return fact;}#ifndef TCPCLIENT_H#define TCPCLIENT_H#include<QtNetwork/QTcpSocket>#include<QByteArray>class tcpClient : public QTcpSocket{    Q_OBJECTpublic:    explicit tcpClient(qintptr handle,QObject *parent = 0);    ~tcpClient();    void writeByte(QByteArray Blocks);//作为客户机的时候用这个函数,作为服务端的socket的时候,这个不用的。signals:    void serverToClientFactByte(qint64 factByte,qintptr handle);//向server发送实际写入的字节    void IWantToClose(qintptr handle);//向server发送我被关闭的信号    void sendForReadMsg(qintptr,QByteArray);//向server发送读取信息成功的信号public slots:   void serverToClientSlots(qintptr handle,const QByteArray &Blocks);//接受server写信号    void clientDisconnect();//这个不需要管。封装好的    void getMSg();//接受到了信息了private:    qintptr handleback;    quint64 blocksize;    QByteArray clientToServerBlocks;};#endif // TCPCLIENT_H#include "tcpsever.h"#include"mydebug.h"TCPSever::TCPSever(QObject *parent) :    QTcpServer(parent){    qRegisterMetaType<qintptr>("qintptr");}void TCPSever::incomingConnection(qintptr handle){    QThread *newClientThread=new QThread;//开辟线程    tcpClient *newClientsocket=new tcpClient(handle);//创建一个socket    newClientsocket->setSocketDescriptor(handle);//设置套接字    strClients temp;//创建一个临时的对象、    newClientsocket->moveToThread(newClientThread);//把这个socket移动到线程中    connect(this,SIGNAL(serverWriteToClientSignal(qintptr,QByteArray)),newClientsocket,SLOT(serverToClientSlots(qintptr,QByteArray)));    connect(newClientsocket,SIGNAL(serverToClientFactByte(qint64,qintptr)),this,SLOT(serverWriteToClientFactByte(qint64,qintptr)));    connect(newClientsocket,SIGNAL(IWantToClose(qintptr)),this,SLOT(clientUserClosed(qintptr)));    connect(newClientsocket,SIGNAL(sendForReadMsg(qintptr,QByteArray)),this,SLOT(clientToserverByte(qintptr,QByteArray)));    temp.clientsSocket=newClientsocket;//保存结构体    temp.clientsSocketThread=newClientThread;    mutex.lock();    Clients.insert(handle,temp);//插入到Qhash中。以后可以根据套接字得到那个结构体,结构体里面存的都是地址。可以用delete删掉    mutex.unlock();    ClientShow newClientMsg;//定义一个结构体,这个结构体是专门发送为GUI线程显示的。    quint16 po;    po=newClientsocket->peerPort();    newClientMsg.ClientPort=QString::number(po);    newClientMsg.ClientName=newClientsocket->peerName();    newClientMsg.ClientIP=newClientsocket->peerAddress().toString();    newClientMsg.handle=handle;    emit sendSpecificHandle(newClientMsg);//告诉GUI来客人啦!    newClientThread->start();#ifdef MYDEBUG    qDebug()<<"新的连接!!";#endif}void TCPSever::clearSpecificSocket(qintptr handle){    //tcpClient *deleteClient=Clients.value(handle);    strClients ClientDelete=Clients.value(handle);    ClientDelete.clientsSocket->disconnectFromHost();    /*    connect(this,SIGNAL(serverWriteToClientSignal(qintptr,QByteArray)),newClientsocket,SLOT(serverToClientSlots(qintptr,QByteArray)));    connect(newClientsocket,SIGNAL(serverToClientFactByte(qint64,qintptr)),this,SLOT(serverWriteToClientFactByte(qint64,qintptr)));    connect(newClientsocket,SIGNAL(IWantToClose(qintptr)),this,SLOT(clientUserClosed(qintptr)));    */    disconnect(this,SIGNAL(serverWriteToClientSignal(qintptr,QByteArray)),ClientDelete.clientsSocket,SLOT(serverToClientSlots(qintptr,QByteArray)));    disconnect(ClientDelete.clientsSocket,SIGNAL(serverToClientFactByte(qint64,qintptr)),this,SLOT(serverWriteToClientFactByte(qint64,qintptr)));    disconnect(ClientDelete.clientsSocket,SIGNAL(IWantToClose(qintptr)),this,SLOT(clientUserClosed(qintptr)));    disconnect(ClientDelete.clientsSocket,SIGNAL(sendForReadMsg(qintptr,QByteArray)),this,SLOT(clientToserverByte(qintptr,QByteArray)));    delete ClientDelete.clientsSocket;    ClientDelete.clientsSocketThread->quit();    ClientDelete.clientsSocketThread->wait();    delete ClientDelete.clientsSocketThread;    mutex.lock();    Clients.remove(handle);    mutex.unlock();}void TCPSever::serverWriteToClient(qintptr handle, const QByteArray &Blocks){    qDebug()<<"serverWriteToClient中的Blocks"<<Blocks;    emit serverWriteToClientSignal(handle,Blocks);}void TCPSever::serverWriteToClientFactByte(qint64 factByte, qintptr handle){    emit writeFinshReturnToGUIFactByte(factByte,handle);}void TCPSever::clientUserClosed(qintptr handle){    clearSpecificSocket(handle);    emit clientUserCLosedToGUI(handle);    qDebug()<<"clientUserClosed";}void TCPSever::clientToserverByte(qintptr handle, QByteArray Blocks){    emit serverReadSucceeToGUI(handle,Blocks);}#ifndef TCPSEVER_H#define TCPSEVER_H#include<QtNetwork/QTcpServer>#include<QThread>#include<QtNetwork/QTcpSocket>#include<QHash>#include"tcpclient.h"#include<QByteArray>#include<QMutex>#include<QMutexLocker>struct strClients{    tcpClient *clientsSocket;    QThread *clientsSocketThread;};class TCPSever : public QTcpServer{    Q_OBJECTpublic:    explicit TCPSever(QObject *parent = 0);    struct ClientShow    {      QString ClientName;      QString ClientIP;      QString ClientPort;      qintptr handle;    };    void incomingConnection(qintptr handle);    void serverWriteToClient(qintptr handle, const QByteArray &Blocks);//由GUI线程调用,向指定的客户机发送指定的内容!    void clearSpecificSocket(qintptr handle);//清除特定的客户机signals:    //下面四个是给GUI发送信号的    void sendSpecificHandle(TCPSever::ClientShow sendClientMsg);//告诉GUI来客人啦!    void serverReadSucceeToGUI(qintptr handle,QByteArray Blocks);//告诉GUI,客户机来信息了。    void writeFinshReturnToGUIFactByte(qint64,qintptr);//向GUI线程返回实际写的字节数    void clientUserCLosedToGUI(qintptr);//由clientUserClosed调用。给GUI的    //这个是给tcpclient发送信号的。     void serverWriteToClientSignal(qintptr handle,const QByteArray &Blocks);//向tcpclient对象发送信号,写指定的内容public slots:    void serverWriteToClientFactByte(qint64 factByte,qintptr handle);//客户机给tcpserver发送的信号,底层封装好了,不用管    void clientUserClosed(qintptr handle);//接受客户机来的信号,并且发送信号给GUI,客人走了    void clientToserverByte(qintptr handle,QByteArray Blocks);//接受客户机发来的写信号。private:    QMutex mutex;//互斥    QHash<qintptr,strClients> Clients; //管理客户机。};#endif // TCPSEVER_H//以下是验证代码...#include "tcpseverui.h"#include "ui_tcpseverui.h"#include"mydebug.h"#include<QList>TcpSeverUi::TcpSeverUi(QWidget *parent) :    QWidget(parent),    ui(new Ui::TcpSeverUi){    ui->setupUi(this);    ui->disConnectionPushButton->setEnabled(false);       ui->label->setText("未监听");   // ui->ClientTableWidget->setRowCount(30);    ui->ClientTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);    ui->ClientTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);    ui->ClientTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);    servers=new TCPSever;   // connect(servers,SIGNAL(sendSpecificHandle(TCPSever::ClientShow)),this,SLOT(getSpecifichandle(TCPSever::ClientShow)));    connect(servers,SIGNAL(sendSpecificHandle(TCPSever::ClientShow)),this,SLOT(getSpecifichandle(TCPSever::ClientShow)));    connect(servers,SIGNAL(writeFinshReturnToGUIFactByte(qint64,qintptr)),this,SLOT(toClientFactByte(qint64,qintptr)));    connect(servers,SIGNAL(clientUserCLosedToGUI(qintptr)),this,SLOT(updateClientMsg(qintptr)));    connect(servers,SIGNAL(serverReadSucceeToGUI(qintptr,QByteArray)),this,SLOT(readOKslot(qintptr,QByteArray)));    qDebug()<<"GUI线程:"<<QThread::currentThreadId();}TcpSeverUi::~TcpSeverUi(){    delete ui;}void TcpSeverUi::on_connectionPushButton_clicked(){   int port=ui->portLineEdit->text().toInt();   if(servers->listen(QHostAddress::Any,port)==true)   {       ui->disConnectionPushButton->setEnabled(true);       ui->connectionPushButton->setEnabled(false);        ui->label->setText("正在监听");   }   else   {       ui->label->setText("打开端口失败!");   }}void TcpSeverUi::on_disConnectionPushButton_clicked(){    servers->close();    ui->connectionPushButton->setEnabled(true);    ui->disConnectionPushButton->setEnabled(false);    ui->label->setText("未监听");}void TcpSeverUi::getSpecifichandle(TCPSever::ClientShow getClientMsg){#ifdef MYDEBUG    qDebug()<<"IP="<<getClientMsg.ClientIP            <<"端口:"<<getClientMsg.ClientPort            <<"名字"<<getClientMsg.ClientName            <<"套接字"<<getClientMsg.handle;#endif    QMutexLocker locker(&mutex);    GUIClientShow.insert(getClientMsg.handle,getClientMsg);    //更新到UI界面    QTableWidgetItem *appenIP,*appenPort,*appendHandle;    appenIP=new QTableWidgetItem(getClientMsg.ClientIP);    appenPort=new QTableWidgetItem(getClientMsg.ClientPort);    int row=ui->ClientTableWidget->rowCount();    ui->ClientTableWidget->insertRow(row);    ui->ClientTableWidget->setItem(row,0,appenIP);    ui->ClientTableWidget->setItem(row,1,appenPort);    //QString handleShow;    //handleShow=QString::number(getClientMsg.handle);    appendHandle=new QTableWidgetItem(QString::number(getClientMsg.handle));    ui->ClientTableWidget->setItem(row,2,appendHandle);    QString k=QString("hello %1,%2").arg(getClientMsg.ClientIP).arg(getClientMsg.ClientPort);    qDebug()<<"发送的内容是"<<k<<"全部大小是"<<k.size();    QByteArray block(k.toStdString().c_str());    servers->serverWriteToClient(getClientMsg.handle,block);}TCPSever::ClientShow TcpSeverUi::readGUIClientMsg(qintptr handle){    QMutexLocker locker(&mutex);    TCPSever::ClientShow temp;    temp.ClientIP=GUIClientShow.value(handle).ClientIP;    temp.ClientName=GUIClientShow.value(handle).ClientName;    temp.ClientPort=GUIClientShow.value(handle).ClientPort;    temp.handle=handle;    return temp;}void TcpSeverUi::toClientFactByte(qint64 factByte, qintptr handle){#ifdef MYDEBUG    qDebug()<<"实际写入的字节是"<<factByte<<",套接字为:"<<handle;#endif}void TcpSeverUi::on_deleteClientPushButton_clicked(){   int currentrow=ui->ClientTableWidget->currentRow();   QTableWidgetItem *handleItem=new QTableWidgetItem;   handleItem=ui->ClientTableWidget->item(currentrow,2);//获取套接字的项   QString handleStr=handleItem->text();   qintptr handle=handleStr.toInt();   servers->clearSpecificSocket(handle);   ui->ClientTableWidget->takeItem(currentrow,0);   ui->ClientTableWidget->takeItem(currentrow,1);   ui->ClientTableWidget->takeItem(currentrow,2);}void TcpSeverUi::updateClientMsg(qintptr handle){    QString t=QString::number(handle);    QList<QTableWidgetItem *> find=ui->ClientTableWidget->findItems(t,Qt::MatchFixedString);    QList<int> row;    for(int i=0;i<find.size();i++)    {        row.append(ui->ClientTableWidget->row(find.at(i)));    }    for(int i=0;i<row.size();i++)    {        ui->ClientTableWidget->takeItem(row.at(i),0);        ui->ClientTableWidget->takeItem(row.at(i),1);        ui->ClientTableWidget->takeItem(row.at(i),2);    }}void TcpSeverUi::readOKslot(qintptr handle, QByteArray Blocks){    qDebug()<<"收到的消息是"<<Blocks;}#ifndef TCPSEVERUI_H#define TCPSEVERUI_H#include <QWidget>#include<tcpsever.h>#include<QHash>#include<QMutexLocker>#include<QMutex>namespace Ui {class TcpSeverUi;}class TcpSeverUi : public QWidget{    Q_OBJECTpublic:    explicit TcpSeverUi(QWidget *parent = 0);    ~TcpSeverUi();    TCPSever::ClientShow readGUIClientMsg(qintptr handle);signals:    //void sendClearHandle(qintptr handle);private slots:    void on_connectionPushButton_clicked();    void getSpecifichandle(TCPSever::ClientShow getClientMsg);    void toClientFactByte(qint64 factByte,qintptr handle);    void on_disConnectionPushButton_clicked();    void updateClientMsg(qintptr handle);    void on_deleteClientPushButton_clicked();    void readOKslot(qintptr handle,QByteArray Blocks);private:    Ui::TcpSeverUi *ui;    TCPSever *servers;    QMutex mutex;    QHash<qintptr,TCPSever::ClientShow> GUIClientShow;};#endif // TCPSEVERUI_H



0 0
原创粉丝点击