网络通信分为阻塞和非阻塞两种,不建议采用阻塞方式。
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"));
}