您的位置:首页 > 理论基础 > 计算机网络

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

2017-10-09 13:30 1231 查看
    Qt实现简单的通信,一般用到UDP和TCP协议,前者是不可靠的协议,后者需要经过三次握手才能创建连接,故为可靠地传输协议;而Websocket协议是基于TCP的一种新的网络协议,它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
    简单的通信,是创建了一个客户端和一个服务端。对基于不同协议的进行简单的学习、总结和协议之间对比。
    通信,最简单的说法就是发消息,无外乎创建连接、客户端向服务端发送消息或者两者互发、接收消息、和断开连接,这几个步骤。理解透了比较简单,总之我觉得记住几个点就可以了。

一、WebSocket

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

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

1、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。

2、client客户端

    使用WebSocket API创建一个简单的客户端。这个过程更简单:根据给的url地址打开连接,从而进行一系列操作。
简单粗暴,上代码,同样参考Qt实例

    值得注意的是,千万记得要在pro文件里添加  QT     += websockets
    Qt详细的对此类的实例,在这里

二、TcpSocket

TCP传输控制协议,面向连接、可靠地传输协议。
代码与websocket很类似。这个参考的文章是:这个,介绍的详细而加简单。

1、客户端
客户端还是很简单,用到了类[b]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);
}
}

2、服务端

服务端比客户端稍复杂点,多了类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()信号,因此为该信号添加槽函数以读取数据

QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);

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

(5) 取消监听

server->close();

三、Udp

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

1、客户端

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;
}

2、服务端

(1)建立套接字

    udpSocket=new QUdpSocket(this);

(2)发送数据

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

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

附加一句,可能错误是有的,但是慢慢改。这只是一个记录。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: