11 Qt的Socket通信

版权声明:原创不易,如引用,请附原文链接 https://blog.csdn.net/Chiang2018/article/details/89293329

Qt中提供的所有的Socket类都是非阻塞的。

  • QTcpServer:用于TCP/IP通信, 作为服务器端套接字使用
  • QTcpSocket:用于TCP/IP通信,作为客户端套接字使用
  • QUdpSocket:用于UDP通信,服务器,客户端均使用此套接字。

1、TCP/IP

客户端:

TcpClientWidget::TcpClientWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TcpClientWidget)
{
    ui->setupUi(this);
    //设置窗口标题
    setWindowTitle("客户端");

    //创建套接字
    tcpSocket = new QTcpSocket(this);
    //连接成功后,进行信号与槽处理
    connect(tcpSocket,&QTcpSocket::connected,this,clientConnect);
    //有数据可读时,进行处理
    connect(tcpSocket,&QTcpSocket::readyRead,this,recvBuffer);
}

void TcpClientWidget::recvBuffer()
{
    QByteArray arr = tcpSocket->readAll();
    ui->RecvtextEdit->append(arr);
}

void TcpClientWidget:: clientConnect()
{
    ui->RecvtextEdit->setText("成功和服务器建立连接");
}

//客户端主动连接服务器
void TcpClientWidget::on_ConnecrpushButton_clicked()
{
    QString ip = ui->IPlineEdit->text();
    quint16 port = ui->PortlineEdit->text().toInt();

    tcpSocket->connectToHost(QHostAddress(ip),port);
}
//发送数据给服务器
void TcpClientWidget::on_SendpushButton_clicked()
{
    //获取编辑框的内容
    QString str = ui->SendtextEdit->toPlainText();
    tcpSocket->write(str.toUtf8().data());
    ui->SendtextEdit->setText("");
}
//断开连接
void TcpClientWidget::on_ClosepushButton_clicked()
{
    tcpSocket->disconnectFromHost();
    tcpSocket->close();

}

服务器:

TcpServerWidget::TcpServerWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TcpServerWidget)
{
    ui->setupUi(this);
    tcpServer = NULL;
    tcpSocket = NULL;
    setWindowTitle("服务器:8888");
    tcpServer= new QTcpServer(this);
    //设置服务器监听
    tcpServer->listen(QHostAddress::Any,8888);
    //当有新连接到达时,进行信号与槽的处理
    connect(tcpServer,&QTcpServer::newConnection,this,&TcpServerWidget::recvConnect);
}

void TcpServerWidget::readBuffer()
{
    QByteArray arr = tcpSocket->readAll();
    ui->ReadtextEdit->append(arr);
}

void TcpServerWidget::recvConnect()
{
    //获取新到达的套接字
    tcpSocket = tcpServer->nextPendingConnection();
    //获取IP地址
    QString str = tcpSocket->peerAddress().toString();
    //获取端口号
    qint16 port = tcpSocket->peerPort();
    QString tmp = QString("[%1,%2]:连接成功!").arg(str).arg(port);
    ui->ReadtextEdit->setText(tmp);
    //当有新数据到达时,进行信号与槽的处理
    connect(tcpSocket,QTcpSocket::readyRead,this,&TcpServerWidget::readBuffer);
}

void TcpServerWidget::on_SendpushButton_clicked()
{
    if(NULL == tcpSocket)
    {
        return;
    }
    QString str = ui->WritetextEdit->toPlainText();
    tcpSocket->write(str.toUtf8().data());
    ui->WritetextEdit->setText("");
}
//关闭套接字
void TcpServerWidget::on_ClosepushButton_clicked()
{
    if(NULL != tcpSocket)
    {
        tcpSocket->disconnectFromHost();
        tcpSocket->close();
        tcpSocket = NULL;
    }

}

2、UDP

使用Qt提供的QUdpSocket进行UDP通信。在UDP方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发送数据。类似的服务器也不从客户端接收连接,只负责调用接收函数,等待来自客户端的数据的到达。在UDP中如果需要接收数据需要通过bind()对套接字进行绑定,只发送数据则不需要对套接字进行绑定。步骤如下:

  1. 创建套接字
  2. 绑定套接字
  3. 接收或者发送数据

接收数据:使用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:数据接收方的端口号
*/

3、广播及组播

1、广播

在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为广播地址:QHostAddress::Broadcast此设置相当于QHostAddress("255.255.255.255")

2、组播

我们再使用广播发送消息的时候会发送给所有用户,但是有些用户是不想接受消息的,这时候我们就应该使用组播,接收方只有先注册到组播地址中才能收到组播消息,否则则接受不到消息。在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为组播地址,关于组播地址的分类:

  1. 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
  2. 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
  3. 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
  4. 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效

注册加入及离开组播地址需要使用QUdpSocket类的成员函数:

bool QUdpSocket::joinMulticastGroup(const QHostAddress & groupAddress);

bool QUdpSocket::leaveMulticastGroup(const QHostAddress & groupAddress);

另外需要注意的时使用组播是,只能使用IPV4的地址,所以我们在绑定套接字的时候,需要显示指定其地址类型为IPV4.

 

猜你喜欢

转载自blog.csdn.net/Chiang2018/article/details/89293329