TCP

网络通信分为阻塞和非阻塞两种,不建议采用阻塞方式。

tcpserver.cpp

#include "tcpserver.h"
#include <QAbstractSocket>
#include <QNetworkInterface>
#include <QDataStream>

TcpServer::TcpServer()
{
    m_socket = NULL;
}

void TcpServer::run()
{
    qDebug() << getIPAddress();

    QTcpServer server;

    //1.1 listen(联系linux网络编程的bind和listen)
    server.listen(QHostAddress::Any, 10000);
    emit signal_stateMessage(QString("listen state: %1").arg(server.isListening()));

    /* waitForNewConnection: This is a blocking function call. Its use is disadvised in a single-threaded GUI application, since the whole application will stop responding until the function returns.
    waitForNewConnection() is mostly useful when there is no event loop available. The non-blocking alternative is to connect to the newConnection() signal. */
    //1.2 waitForNewConnection
    if( !server.waitForNewConnection(30000) )
    {
        emit signal_stateMessage(server.errorString());

        return;
    }

    emit signal_stateMessage(QString("waitForNewConnection successed, new connection established"));

    //2. nextPendingConnection(联系linux网络编程的accept)
    m_socket = server.nextPendingConnection();
    connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slot_error(QAbstractSocket::SocketError)));
    qDebug() << m_socket;

    emit signal_stateMessage(QString("%1 is connected").arg(m_socket->peerAddress().toString()));

    //3. write(or read)
    while (m_socket->state() & QAbstractSocket::ConnectedState)
    {
        m_socket->write("hello world ");
        m_socket->waitForBytesWritten();
        m_socket->write("bye\n");
        m_socket->waitForBytesWritten();

        QThread::msleep(1000);
    }

//    //3. write(or read)
//    QByteArray block;
//    QDataStream out(&block, QIODevice::ReadWrite);
//    out.setVersion(QDataStream::Qt_5_5);
//    out << (quint16)0;
//    out << tr("hello\n");
//    out.device()->seek(0);
//    out << (quint16)(block.size() - sizeof(quint16));

//    m_socket->write(block);
//    m_socket->waitForBytesWritten();


    //4. close
    m_socket->close();
    server.close();

    emit signal_stateMessage(QString("close"));

}

QString TcpServer::getIPAddress()
{
    QString ipAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    for (int i = 0; i < ipAddressesList.size(); ++i)
    {
        if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
            ipAddressesList.at(i).toIPv4Address())
        {
            ipAddress = ipAddressesList.at(i).toString();
            break;
        }
    }
    if (ipAddress.isEmpty())
        ipAddress = QHostAddress(QHostAddress::LocalHost).toString();

    return ipAddress;
}

void TcpServer::slot_error(QAbstractSocket::SocketError errormsg)
{
//    emit signal_stateMessage(errormsg.errorString());
    emit signal_stateMessage(m_socket->errorString());

    //4. close
    m_socket->close();//attention, close while error occurs
}

tcpclient.cpp

#include "tcpclient.h"
//#include <QAbstractSocket>
#include <QNetworkInterface>
#include <QDataStream>

TcpClient::TcpClient()
{
//    m_socket = new QTcpSocket();//error:          Object: Cannot create children for a parent that is in a different thread.
                                  //cause of error: all the memeber decfined in QThread belong to QThread's parent's thread, so m_socket which is initialized in constructor belongs to parent's thread, so that calling m_socket is cross-thread operation.
                                  //solution:       move m_socket to function run

}

void TcpClient::run()
{
    QTcpSocket socket;//local var avoid memory leak
    qDebug() << &socket;

    //1.1 connectToHost(联系linux网络编程connect)
    socket.connectToHost("localhost", 10000);

    /* Note: This function may fail randomly on Windows. Consider using the event loop and the connected() signal if your software will run on Windows. */
    //1.2 waitForConnected
    if( !socket.waitForConnected(5000) )
    {
        emit signal_stateMessage(socket.errorString());

        return;
    }

    emit signal_stateMessage(QString("waitForConnected success, connects to %1").arg(socket.peerAddress().toString()));

    //2. read(or write)
    while (socket.state() & QAbstractSocket::ConnectedState)
    {
        socket.waitForReadyRead(10000);
        QString recv = QString(socket.readLine());

        emit signal_message(recv);
    }

//    //2. read(or write)
//    socket.waitForReadyRead();

//    m_blockSize = 0;
//    QDataStream in(&socket);
//    in.setVersion(QDataStream::Qt_5_5);
//    if(m_blockSize == 0)
//    {
//        if( socket.bytesAvailable() < (int)sizeof(quint16) )
//            return;
//        in >> m_blockSize;
//    }
//    if(socket.bytesAvailable() < m_blockSize)
//        return;
//    QString message;
//    in >> message;

//    emit signal_message(message);

    //3. close
    socket.close();

    emit signal_stateMessage(QString("close"));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值