Qt TCP/IP网络编程

        Qt学习之路七——TCP/IP网络编程_技术小白的博客-CSDN博客

        在qt中的网络编程和之前在windows中的网络编程的基本步骤是一样的,服务器有两个套接字,一个负责监听(QTcpServer),还有一个负责通信(QTcpSocket),客户端只有一个负责通信的套接字(QTcpSocket)。

添加:

QT       += network

添加:

#include "QTcpSocket"
#include "QTcpServer"

1、QTcpServer对象负责监听是否有客户端连接此服务器。它是通过这样一个函数监听的

 tcpserver->listen(QHostAddress::Any, 8888);

它的第一个参数表示服务器监听的地址,如果后面是Any表示监听本机的所有网口的,第二个参数表示监听的网络端口。

2、如果服务器监听到有客户端和它进行连接,服务器就会触发newConnection这个信号。同时客户端一旦和服务器连接成功,客户端会触发connected这个信号,表示已经成功和服务器连接。

3、在两者建立好连接之后,服务器需要返回一个QTcpSocket对象来和客户端进行通信,通常通过这个函数来返回一个建立好连接的套接字。

tcpsocket = tcpserver->nextPendingConnection();

4、接着就可以通过两这的通信套接字来完成通信。当一端发送成功之后,接收方会触发这么一个信号,readyRead,这样我们就能够读取套接字当中的内容了。

5、断开连接的时候我们使用这样的函数

tcpsocket->disconnectFromHost();

现在我们就通过Qt Creator来实现客户端和服务器进行通信。

一、客户端编程

1) 初始化QTcpSocket 

在构造函数中,我们需要先对其进行实例化,并连接信号与槽函数:

    //初始化TCP客户端
    tcpClient = new QTcpSocket(this);   //实例化tcpClient
    tcpClient->abort();                 //取消原有连接
    connect(tcpClient, SIGNAL(readyRead()), this, SLOT(ReadData()));
    connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), \
            this, SLOT(ReadError(QAbstractSocket::SocketError)));

2)建立连接 和 断开连接

    tcpClient->connectToHost(ui->edtIP->text(), ui->edtPort->text().toInt());
    if (tcpClient->waitForConnected(1000))  // 连接成功则进入if{}
    {
        ui->btnConnect->setText("断开");
        ui->btnSend->setEnabled(true);
    }

3)读取服务器发送过来的数据 

readyRead()是QTcpSocket从父类QIODevice中继承下来的信号:This signal is emitted once every time new data is available for reading from the device’s current read channel。 
readyRead()对应的槽函数为:

void MyTcpClient::ReadData()
{
    QByteArray buffer = tcpClient->readAll();
    if(!buffer.isEmpty())
    {
        ui->edtRecv->append(buffer);
    }
}

4)向服务器发送数据

    QString data = ui->edtSend->toPlainText();
    if(data != "")
    {
        tcpClient->write(data.toLatin1()); //qt5去除了.toAscii()
    }

至此,通过4步,我们就完成了TCP Client的程序开发

二:服务器端编程 

        服务器段编程相比于客户端要繁琐一些,因为对于客户端来说,只能连接一个服务器。而对于服务器来说,它是面向多连接的,如何协调处理多客户端连接就显得尤为重要。 
前言:编程过程中遇到的问题 和 解决的方法 
遇到的问题:每个新加入的客户端,服务器给其分配一个SocketDescriptor后,就会emit newConnection()信号,但分配好的SocketDecriptor并没有通过newConnection()信号传递,所以用户得不到这个客户端标识SocketDescriptor。同样的,每当服务器收到新的消息时,客户端会emit readReady()信号,然而readReady()信号也没有传递SocketDescriptor, 这样的话,服务器端即使接收到消息,也不知道这个消息是从哪个客户端发出的。

解决的方法: 
1. 通过重写[virtual protected] void QTcpServer::incomingConnection(qintptr socketDescriptor),获取soketDescriptor。自定义TcpClient类继承QTcpSocket,并将获得的soketDescriptor作为类成员。 这个方法的优点是:可以获取到soketDescriptor,灵活性高。缺点是:需要重写函数、自定义类。 
2. 在newConnection()信号对应的槽函数中,通过QTcpSocket *QTcpServer::nextPendingConnection()函数获取 新连接的客户端:Returns the next pending connection as a connected QTcpSocket object. 虽然仍然得不到soketDescriptor,但可以通过QTcpSocket类的peerAddress()和peerPort()成员函数获取客户端的IP和端口号,同样是唯一标识。 优点:无需重写函数和自定义类,代码简洁。缺点:无法获得SocketDecriptor,灵活性差。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_42475191

谢谢老板

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值