• qt QTcpServer与QTcpSocket通讯


    分类: C/C++

    TCP
            TCP是一个基于流的协议。对于应用程序,数据表现为一个长长的流,而不是一个大大的平面文件。基于TCP的高层协议通常是基于行的或者基于块的。
              ●、基于行的协议把数据作为一行文本进行传输,每行都以一个换行符结尾。
              ●、基于块的协议把数据作为二进制块进行传输,每块是由一个size大小字段和紧跟它的一个size字节的数据组成。
            QTcpSocket通过器父类QAbstractSocket继承了QIODevice,因此他可以通过使用QTextStream和QDataStream来进行读取和写入。
            QTcpServer类在服务器端处理来自TCP客户端连接数据,需要注意的是,该类直接继承于QObject基类,而不是QAbstractSocket抽象套接字类。
     
    一 QTcpServer
    #ifndef VXMAINWINDOW_H
    #define VXMAINWINDOW_H
    #include <QWidget>
    #include <QtNetwork/QTcpServer>
    #include <QtNetwork/QTcpSocket>
    class QPushButton;
    class QTextEdit;
    class CVxMainWindow : public QWidget
    {
     Q_OBJECT
    public:
     CVxMainWindow(QWidget *parent = NULL);
     ~CVxMainWindow();
    protected:
     void resizeEvent(QResizeEvent *);
    private slots:
     void Btn_ListenClickedSlot();
     void Btn_StopListenClickedSlot();
     void newConnectionSlot();
     void dataReceived();
    private:
     QTcpServer *m_pServer;
     QTcpSocket *m_pSocket;
     QPushButton *m_pBtn_Listen;
     QPushButton *m_pBtn_StopListen;
     QTextEdit   *m_pEdt_Info;
    };
    #endif // VXMAINWINDOW_H
     
    #include "VxMainWindow.h"
    #include <QtGui/QtGui>
    CVxMainWindow::CVxMainWindow(QWidget *parent)
     : QWidget(parent)
    {
     m_pBtn_Listen     = new QPushButton(QObject::tr("开始监听"), this);
     m_pBtn_StopListen = new QPushButton(QObject::tr("停止监听"), this);
     m_pEdt_Info = new QTextEdit(this);
     m_pServer = new QTcpServer(this);
     
     connect(m_pBtn_Listen,     SIGNAL(clicked()), this, SLOT(Btn_ListenClickedSlot()));
     connect(m_pBtn_StopListen, SIGNAL(clicked()), this, SLOT(Btn_StopListenClickedSlot()));
     connect(m_pServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
    }
    CVxMainWindow::~CVxMainWindow()
    {
    }
    void CVxMainWindow::resizeEvent(QResizeEvent *)
    {
     m_pBtn_Listen->setGeometry(10, 5, 80, 20);
     m_pBtn_StopListen->setGeometry(100, 5, 80, 20);
     m_pEdt_Info->setGeometry(0, 30, width(), height() - 30);
    }
    void CVxMainWindow::Btn_ListenClickedSlot()
    {
     if (!m_pServer->isListening())
     {
      if (m_pServer->listen(QHostAddress::Any, 8080)) 
      {
       m_pEdt_Info->append(QObject::tr("打开监听端口成功!"));
      }
      else
      {
       m_pEdt_Info->append(QObject::tr("打开监听端口失败!"));
      }
     }
     else
     {
      m_pEdt_Info->append(QObject::tr("正在监听中...!"));
     }
    }
    void CVxMainWindow::Btn_StopListenClickedSlot()
    {
     if (m_pServer->isListening())
     {
      m_pServer->close();
      m_pEdt_Info->append(QObject::tr("停止监听!"));
     }
    }
    void CVxMainWindow::newConnectionSlot()
    {
     m_pEdt_Info->append(QObject::tr("有新客户端连接到服务器"));
     m_pSocket = m_pServer->nextPendingConnection();
     connect(m_pSocket, SIGNAL(disconnected()), m_pSocket, SLOT(deleteLater()));
     connect(m_pSocket, SIGNAL(readyRead()),this, SLOT(dataReceived()));
     int length = 0;
     QString vMsgStr = QObject::tr("Welcome");
     if((length=m_pSocket->write(vMsgStr.toLatin1(),vMsgStr.length()))!=vMsgStr.length())
     {
     }
    }
    void CVxMainWindow::dataReceived()
    {
     while(m_pSocket->bytesAvailable())
     {       
      QByteArray vTemp;
      vTemp = m_pSocket->readLine();  
      QString vTempStr(vTemp);
      m_pEdt_Info->append(vTempStr);
      int length = 0;
      QString vMsgStr = QObject::tr("回复:") + vTempStr;
      if((length=m_pSocket->write(vMsgStr.toLatin1(),vMsgStr.length()))!=vMsgStr.length())
      {
      }
     }
    }
     
    二 QTcpSocket
     
     
    #ifndef VXMAINWINDOW_H
    #define VXMAINWINDOW_H
    #include <QWidget>
    #include <QtNetwork/QTcpSocket>
    #include <QtNetwork/QHostAddress>
    class QPushButton;
    class QTextEdit;
    class QLineEdit;
    class CVxMainWindow : public QWidget
    {
     Q_OBJECT
    public:
     CVxMainWindow(QWidget *parent = NULL);
     ~CVxMainWindow();
    protected:
     void resizeEvent(QResizeEvent *);
    private slots:
     void Btn_ConnectClickedSlot();
     void Btn_DisConnectClickedSlot();
     void Btn_SendClickedSlot();
     void connectedSlot();
     void disconnectedSlot();
     void dataReceived();
     void displayError(QAbstractSocket::SocketError);
    private:
     QTcpSocket *m_pSocket;
     QHostAddress m_HostAddress;
     QPushButton *m_pBtn_Connect;
     QPushButton *m_pBtn_DisConnect;
     QTextEdit   *m_pEdt_Info;
     QLineEdit   *m_pEdt_Send;
     QPushButton *m_pBtn_Send;
    };
    #endif // VXMAINWINDOW_H
     
    #include "VxMainWindow.h"
    #include <QtGui/QtGui>
    CVxMainWindow::CVxMainWindow(QWidget *parent)
     : QWidget(parent)
    {
     m_pBtn_Connect    = new QPushButton(QObject::tr("连接服务器"), this);
     m_pBtn_DisConnect = new QPushButton(QObject::tr("断开连接"), this);
     m_pEdt_Send       = new QLineEdit(this);
     m_pBtn_Send       = new QPushButton(QObject::tr("发送"), this);
     m_pEdt_Info = new QTextEdit(this);
     m_pSocket = new QTcpSocket(this);
     connect(m_pBtn_Connect,    SIGNAL(clicked()), this, SLOT(Btn_ConnectClickedSlot()));
     connect(m_pBtn_DisConnect, SIGNAL(clicked()), this, SLOT(Btn_DisConnectClickedSlot()));
     connect(m_pBtn_Send,       SIGNAL(clicked()), this, SLOT(Btn_SendClickedSlot()));
     connect(m_pSocket, SIGNAL(connected()), this, SLOT(connectedSlot()));
     connect(m_pSocket, SIGNAL(disconnected()), this, SLOT(disconnectedSlot()));
     connect(m_pSocket, SIGNAL(readyRead()),this, SLOT(dataReceived()));
     connect(m_pSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
    }
    CVxMainWindow::~CVxMainWindow()
    {
    }
    void CVxMainWindow::resizeEvent(QResizeEvent *)
    {
     m_pBtn_Connect->setGeometry(10, 5, 80, 20);
     m_pBtn_DisConnect->setGeometry(100, 5, 80, 20);
     m_pEdt_Send->setGeometry(10, 30, 150, 20);
     m_pBtn_Send->setGeometry(170, 30, 80, 20);
     m_pEdt_Info->setGeometry(0, 60, width(), height() - 60);
    }
    void CVxMainWindow::Btn_ConnectClickedSlot()
    {
     m_HostAddress.setAddress(QObject::tr("127.0.0.1"));
     m_pSocket->connectToHost(m_HostAddress, 8080);
    }
    void CVxMainWindow::Btn_DisConnectClickedSlot()
    {
     m_pSocket->disconnectFromHost();
    }
    void CVxMainWindow::Btn_SendClickedSlot()
    {
     int length = 0;
     QString vMsgStr = m_pEdt_Send->text();
     if((length = m_pSocket->write(vMsgStr.toLatin1(),vMsgStr.length())) != vMsgStr.length())
     {
      m_pEdt_Info->append(QObject::tr("发送信息失败:") + vMsgStr);
     }
    }
    void CVxMainWindow::connectedSlot()
    {
     m_pEdt_Info->append(QObject::tr("成功连接到服务器!"));
    }
    void CVxMainWindow::disconnectedSlot()
    {
     m_pEdt_Info->append(QObject::tr("断开与服务器的连接!"));
    }
    void CVxMainWindow::dataReceived()
    {
     while(m_pSocket->bytesAvailable())
     {       
      QString vTemp;
      vTemp = m_pSocket->readLine();          
      m_pEdt_Info->append(vTemp);
     }
    }
    void CVxMainWindow::displayError(QAbstractSocket::SocketError)
    {
    }
     
    以上代码在发送和接受串中带中文时会出现乱码,下面提供另外的发送和接受方法:
    1 发送:
    void XXX()
    {
     // 用于暂存我们要发送的数据
     QByteArray block; 
     // 使用数据流写入数据
     QDataStream out(&block,QIODevice::WriteOnly);
     // 设置数据流的版本,客户端和服务器端使用的版本要相同
     out.setVersion(QDataStream::Qt_4_7);
     out<<(quint16) 0;
     out<<QObject::tr("您好啊!");
     out.device()->seek(0);
     out<<(quint16)(block.size() - sizeof(quint16));
     m_pSocket->write(block);
    }
    2 接受:
    void CVxMainWindow::dataReceived()
    {
     QString vTempStr;  
     quint16 blockSize = 0;
     QDataStream in(m_pSocket);
     // 设置数据流版本,这里要和服务器端相同
     in.setVersion(QDataStream::Qt_4_7);
     // 如果是刚开始接收数据
     if(blockSize == 0) 
     {
      //判断接收的数据是否有两字节,也就是文件的大小信息
      //如果有则保存到blockSize变量中,没有则返回,继续接收数据
      if(m_pSocket->bytesAvailable() < (int)sizeof(quint16)) return;
      in >> blockSize;
     }
     // 如果没有得到全部的数据,则返回,继续接收数据
     if(m_pSocket->bytesAvailable() < blockSize) return;
     in >> vTempStr;
     m_pEdt_Info->append(vTempStr);
    }
  • 相关阅读:
    Introduction to Computer Science and Programming in Python--MIT
    随机变量及其分布
    条件期望与重期望
    Fourier级数
    Windows进程通信-共享内存空间
    windows网络编程-socket
    PE文件中找导出表
    PE文件结构体-IMAGE_DATA_DIRECTORY
    RVA到FOA的转换
    PE文件结构体-IMAGE_SECTION_HEADER
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/3746925.html
Copyright © 2020-2023  润新知