Socket通信
Qt中提供的所有的Socket类都是
非阻塞的。
Qt中常用的用于socket通信的套接字类:
- QTcpServer用于TCP/IP通信, 作为服务器端套接字使用。
- QTcpSocket用于TCP/IP通信,作为客户端套接字使用。
- QUdpSocket用于UDP通信,服务器,客户端均使用此套接字。
TCP/IP
在Qt中实现TCP/IP服务器端通信的流程:
- 创建套接字
- 将套接字设置为监听模式
- 等待并接受客户端请求 可以通过QTcpServer提供的void newConnection()信号来检测是否有连接请求,如果有可以在对应的槽函数中调用nextPendingConnection函数获取到客户端的Socket信息(返回值为QTcpSocket*类型指针),通过此套接字与客户端之间进行通信。
- 接收或者向客户端发送数据 接收数据:使用read()或者readAll()函数
- 发送数据:使用write()函数
- 客户端通信流程:
- 1.创建套接字 ;
- 2.连接服务器 可以使用QTcpSocket类的connectToHost()函数来连接服务器。
- 3.向服务器发送或者接受数据 ;### 服务器端:
通过Qt提供的QTcpServer类实现服务器端的socket通信:
classTCPServer:publicQMainWindow{
Q_OBJECT
public:explicitTCPServer(QWidget *parent =0);~TCPServer();public slots:voidslotNewConnection();voidslotReadyRead();private:
Ui::TCPServer *ui;// 负责监听的套接字
QTcpServer* m_server;// 负责通信的套接字
QTcpSocket* m_client;};//---------- tcpserver.cpp ------------TCPServer::TCPServer(QWidget *parent):QMainWindow(parent),ui(new Ui::TCPServer),m_server(NULL),m_client(NULL){
ui->setupUi(this);//创建套接字对象
m_server =newQTcpServer(this);//将套接字设置为监听模式
m_server->listen(QHostAddress::Any,9999);//通过信号接收客户端请求connect(m_server,&QTcpServer::newConnection,this,&TCPServer::slotNewConnection);}TCPServer::~TCPServer(){delete ui;}voidTCPServer::slotNewConnection(){if(m_client ==NULL){//处理客户端的连接请求
m_client = m_server->nextPendingConnection();//发送数据
m_client->write("服务器连接成功!!!");//连接信号, 接收客户端数据connect(m_client,&QTcpSocket::readyRead,this,&TCPServer::slotReadyRead);}}voidTCPServer::slotReadyRead(){//接收数据
QByteArray array = m_client->readAll();QMessageBox::information(this,"Client Message", array);}
客户端:
客户端通过使用Qt提供的QTcpSocket类可以方便的实现与服务器端的通信。
//------------- tcpclient.h ------------classTCPClient:publicQMainWindow{
Q_OBJECT
public:explicitTCPClient(QWidget *parent =0);~TCPClient();public slots:voidslotReadyRead();voidslotSendMsg();private:
Ui::TCPClient *ui;
QTcpSocket* m_client;};//------------- tcpclient.cpp --------------TCPClient::TCPClient(QWidget *parent):QMainWindow(parent),ui(new Ui::TCPClient){
ui->setupUi(this);//创建套接字
m_client =newQTcpSocket(this);//连接服务器
m_client->connectToHost(QHostAddress("127.0.0.1"),9999);//通过信号接收服务器数据connect(m_client,&QTcpSocket::readyRead,this,&TCPClient::slotReadyRead);//发送按钮connect(ui->btnSend,&QPushButton::clicked,this,&TCPClient::slotSendMsg);}TCPClient::~TCPClient(){delete ui;}voidTCPClient::slotReadyRead(){//接收数据
QByteArray array = m_client->readAll();QMessageBox::information(this,"Server Message", array);}voidTCPClient::slotSendMsg(){
QString text = ui->textEdit->toPlainText();//发送数据
m_client->write(text.toUtf8());
ui->textEdit->clear();}
UDP:
使用Qt提供的QUdpSocket进行UDP通信。在UDP方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发送数据。类似的服务器也不从客户端接收连接,只负责调用接收函数,等待来自客户端的数据的到达。
在UDP通信中,服务器端和客户端的概念已经显得有些淡化,两部分做的工作都大致相同:
- 创建套接字
- 绑定套接字 在UDP中如果需要接收数据则需要对套接字进行绑定,只发送数据则不需要对套接字进行绑定。 通过调用bind()函数将套接字绑定到指定端口上。
- 接收或者发送数据 - 接收数据:使用readDatagram()接收数据,函数声明如下:
qint64 readDatagram(char* data, qint64 maxSize,
QHostAddress * address =0, quint16 * port =0)//data: 接收数据的缓存地址//maxSize: 缓存接收的最大字节数//address: 数据发送方的地址(一般使用提供的默认值)//port: 数据发送方的端口号(一般使用提供的默认值)
使用pendingDatagramSize()可以获取到将要接收的数据的大小,根据该函数返回值来准备对应大小的内存空间存放将要接收的数据。
- 发送数据: 使用writeDatagram()函数发送数据,函数声明如下:
qint64 writeDatagram(const QByteArray & datagram,const QHostAddress & host, quint16 port)//datagram:要发送的字符串//host:数据接收方的地址//port:数据接收方的端口号
广播:
- 在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为广播地址:QHostAddress::Broadcast此设置相当于QHostAddress(“255.255.255.255”)使用UDP广播的的特点:
- 使用UDP进行广播,局域网内的其他的UDP用户全部可以收到广播的消息
- UDP广播只能在局域网范围内使用
组播:
我们再使用广播发送消息的时候会发送给所有用户,但是有些用户是不想接受消息的,这时候我们就应该使用组播,接收方只有先注册到组播地址中才能收到组播消息,否则则接受不到消息。另外组播是可以在Internet中使用的。
在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为组播地址,关于组播地址的分类:
- 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
- 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
- 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
- 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内; 注册加入到组播地址需要使用QUdpSocket类的成员函数:
booljoinMulticastGroup(const QHostAddress & groupAddress);
TCP/IP 和 UDP的区别:
TCP/IP UDP
是否连接 面向连接 无连接
传输方式 基于流 基于数据报
传输可靠性 可靠 不可靠
传输效率 效率低 效率高
能否广播 不能 能
版权归原作者 23Hour摸鱼 所有, 如有侵权,请联系我们删除。