简单的通信(QUdpSocket、 QTcpSocket、QWebSocket)--Qt网络

 

    Qt实现简单的通信,一般用到UDP和TCP协议,前者是不可靠的协议,后者需要经过三次握手才能创建连接,故为可靠地传输协议;而Websocket协议是基于TCP的一种新的网络协议,它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
    简单的通信,是创建了一个客户端和一个服务端。对基于不同协议的进行简单的学习、总结和协议之间对比。

 

    通信,最简单的说法就是发消息,无外乎创建连接、客户端向服务端发送消息或者两者互发、接收消息、和断开连接,这几个步骤。理解透了比较简单,总之我觉得记住几个点就可以了。

 

WebSocket

    WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并允许数据进行双向传送。——- 《维基百科》

    WebSocket 协议使用 ws: 和 wss: URL 协议,以分别代表不安全和安全的 WebSocket 请求。

 

server服务端

    用Qt建立服务端用到了类QWebSocketServer、和QWebSocket 。码参考是Qt自带的实例。大概流程就是:

(1)监听端口port,即告诉服务器监听地址和端口的传入连接情况,当有连接将新连接信号和处理槽绑定,关闭信号依然,方便后面的处理。

if (m_pWebSocketServer->listen(QHostAddress::Any, port))
{
        if (m_debug)
            qDebug() << "Echoserver listening on port" << port;
        connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
                this, &EchoServer::onNewConnection);
        connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed);
    }

在当发出有新连接信号时,槽获取客户端的连接

QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();

(2)在创建好连接,可以用pSocket接收数据,发送数据等。

    connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage);
    connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage);
    connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected);

    在实例代码中,看到了QObject的函数 sender()。简单提一句:当某一个目标emit一个信号的时候,它就是一个sender,系统会记录下当前是谁emit出这个signal的,所以在对应的slot里就可以通过 sender()得到当前是谁调用了了这个槽,对应的是QObject->d->sender。

 

client客户端

 

    使用WebSocket API创建一个简单的客户端。这个过程更简单:根据给的url地址打开连接,从而进行一系列操作。

简单粗暴,上代码,同样参考Qt实例。

    值得注意的是,千万记得要在pro文件里添加  QT     += websockets

    Qt详细的对此类的实例,在这里。

 

TcpSocket

TCP传输控制协议,面向连接、可靠地传输协议。

代码与websocket很类似。这个参考的文章是:这个,介绍的详细而更加简单。

 

客户端

客户端还是很简单,用到了类QTcpSocket。用到还是那几个:

(1)连接服务器(在创建好套接字的基础上)

tcpSocket->connectToHost(*serverIP,port);

 

(2)发送信息,这个和WebSocket有点不一样,用的是Write()函数。类似这样:

tcpSocket->write(msg.toLatin1();

 

(3)接收信息 ,看到两种接收方式,都贴出来。一个用的read(char * data, qint64 maxSize),一个用的readAll()。

方式一:

    while(tcpSocket->bytesAvailable()>0)
    {
        QByteArray datagram;
        datagram.resize(tcpSocket->bytesAvailable());
        tcpSocket->read(datagram.data(),datagram.size());
        QString msg=datagram.data();
        contentListWidget->addItem(msg.left(datagram.size()));
    }

 

方式二: 

 

void TcpClient::dataReceived()
{
    QByteArray buffer;  
      //读取缓冲区数据  
      buffer = socket->readAll();  
      if(!buffer.isEmpty())  
      {  
          QString str = ui->textEdit_Recv->toPlainText();  
          str+=tr(buffer);  
          //刷新显示  
          ui->textEdit_Recv->setText(str);  
      } 
}

 

 

服务端

 

服务端比客户端稍复杂点,多了类QTcpServer。感觉除了多了监听,也没多大区别。

 

(1)监听端口

server->listen(QHostAddress::Any,port);


(2)当服务器被客户端访问时,发出信号,转到槽。

connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);  
  
void MainWindow::server_New_Connect()  
{  
    //获取客户端连接  
    socket = server->nextPendingConnection();  
}  

(3)发送信息

socket->write(data);

(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据。

void MainWindow::socket_Read_Data()  
{  
    QByteArray buffer;  
    //读取缓冲区数据  
    buffer = socket->readAll();  
}  

 

 

(5) 取消监听

 

 
  1. server->close();

 

Udp

 

    UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接传输层协议,提供面向事务的简单不可靠信息传送服务。-------百度百科

 

客户端

 

udp客户端只用到一个类 ,即QUdpSocket。因为udp是一种无连接的传输协议,所以无需像上面的协议建立连接过程更加简单。

(1)建立套接字

    udpSocket=new  QUdpSocket(this);

 

(2)通过信号readyRead()发出,可调用槽来接收数据。

connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
void UdpClient::dataReceived()
{
    while(udpSocket->hasPendingDatagrams())  //有未处理的报文
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());
        QString msg=datagram.data();
        receiveTextEdit->insertPlainText(msg);
    }
}
 
 

 

(3)绑定端口

    bool result=udpSocket->bind(port);  //绑定端口
    if(!result)
    {
        QMessageBox::information(this,tr("error"),tr("udp socket create error"));
        return;
    }

 

 

 

 

服务端

 

(1)建立套接字

    udpSocket=new QUdpSocket(this);

 

(2)发送数据

udpSocket->writeDatagram(msg.toLatin1(),QHostAddress::Broadcast,port);

 

从上面可以看出,这几个协议都差不多,可靠地协议就是要建立连接,断开连接,而 无连接的不可靠的协议,无需建立连接,直接绑定端口,就可以了。

 

 

附加一句,可能错误是有的,但是慢慢改。这只是一个记录。

 

你可能感兴趣的:(qt,Qt,Widgets)