Qt TCP通信(QTcpSocket)

1. 用法

下面以初始化、连接、写、读、断开连接这几个部分来介绍QTcpSocket的用法。
假设在xxx类实现tcp通信。

初始化

/* 初始化 */
void xxx::init() {
	m_socket = new QTcpSocket(this);

	/*下面是几种常用的信号,更多的信号可以查看QAbstractSocket和QIODevice文档*/
	connect(m_socket, &QTcpSocket::connected, this, [] () {
		qDebug() << "socket已连接";
	});

	connect(m_socket, &QTcpSocket::disconnected, this, [] () {
		qDebug() << "socket已断开连接";
	});

	connect(m_socket, &QTcpSocket::stateChanged, this, [] (QAbstractSocket::SocketState socketState) {
		qDebug() << "socket状态改变" << socketState;
	});

	connect(m_socket, &QTcpSocket::readyRead, this, [] () {
		qDebug() << "有数据可读";
	});
}

连接

/* 初始化 */
bool xxx::connect() {
	m_socket->connectToHost(m_ip, m_port); //连接
	
	/* 等待连接完成,设置连接超时为500ms,超时视为连接失败 */
    return m_socket->waitForConnected(500); 
}

发送

/* 发送数据 */
bool xxx::send(const QByteArray &byteArray) {
	if (m_socket->write(byteArray) == -1) {
		/* 写数据时出现错误 */
		qDebug() << m_socket->errorString(); //错误的详情
		return false;
	}

    if (!m_socket->waitForBytesWritten(500)) {//等待发送完毕,设置超时时间500ms
        /* 限定时间内没发完 */
        return false;
    }
	
	return true;
}

接收

/* 接收数据 */
QByteArray xxx::receive() {
	/* readAll返回空的数据不一定代表有错,该方法无法判断是否出错 */
	return m_socket->readAll();
}

断开连接

/* 接收数据 */
void xxx::disconnect() {
	/** 写法一 
	 * 该方法调用后会开始断开连接。
	 * 要注意的是,调用这个方法后,不会马上断开连接,
	 * 它会等待数据写入完成后才会真正断开,如果数据一直写不完就一直断不开
	 * 比如拔了网线,就一直写不进去,这时候调用这个方法是无效的,
	 * socket状态一直为ClosingState。
	 */
	m_socket->disconnectFromHost();	//

	/** 写法二 
	 * 该方法调用后会立马断开连接。
	 */
	m_socket->abort();  
	
}

2.应用

判断连接是否断开

1、发送数据时,一次或多次发送超时,可以判断为断开连接。
2、心跳包检测(每隔一段时间发送一条无意义的数据,根据发送结果确认连接状态),TCP连接一般都要加上这条,不然如果长时间无数据发送,连接会被自动关闭。
注:检测到断开连接最好调用abort来断开socket上的连接,原因在上一节已有说明。

同步操作

QTcpSocket的方法是异步的,调用了函数,不会马上返回结果,Qt通过信号来异步返回结果,但有时候需要同步得到结果,对此,QTcpSocket提供了以下函数,可以阻塞线程,直到指定的信号被触发。

bool waitForConnected(int msecs = 30000); //阻塞线程,直到连接完成或超时。
bool waitForReadyRead(int msecs = 30000); //阻塞线程,直到有新数据可读取或超时。
bool waitForBytesWritten(int msecs = 30000); //阻塞线程,直到数据被写入socket或超时。
bool waitForDisconnected(int msecs = 30000); //阻塞线程,直到断开连接或超时。
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: QTTCP通信使用线程池可以提高系统的并发性和响应性。通常情况下,使用单个线程来处理TCP通信可能会导致系统在处理大量连接时出现阻塞,影响系统的性能。 通过使用线程池,可以将TCP通信任务分配给多个线程来处理,从而使系统能够同时处理多个连接。线程池包含一组线程,这些线程在需要时可以立即执行任务。这样,可以确保每个连接都能获得足够的CPU时间,而不会被其他连接阻塞。 QT的线程池机制可以方便地管理线程的生命周期,分配和回收线程资源。当一个连接建立时,可以从线程池中获取一个线程来处理该连接,当连接终止时,可以将线程归还给线程池。这种方式可以避免不断创建和销毁线程的开销,提高系统的效率。 通过使用线程池,还可以实现线程的复用。当一个连接完成任务后,并不立即销毁线程,而是将线程放回线程池,以供下一个连接使用。这样可以避免线程的频繁创建和销毁,减少系统的开销,提高系统的性能。 总而言之,QTTCP通信使用线程池可以提高系统的并发性和响应性,减少线程的创建和销毁开销,提高系统的性能和效率。 ### 回答2: 在Qt中,TCP通信可以使用线程池来实现。线程池是一种管理和调度多个线程的机制,可以有效地利用系统资源并提高程序的性能。 在使用Qt进行TCP通信时,我们可以使用QtQtConcurrent模块配合线程池来处理通信任务。QtConcurrent模块提供了一些方便的类和函数来进行并行编程,其中就包括了线程池。 首先,我们需要创建一个线程池对象,并指定线程池中的线程数量。可以根据需要来调整线程数量,以避免线程过多或过少造成的资源浪费或程序性能下降。 然后,我们可以使用QtConcurrent::run()函数来将需要执行的通信任务放入线程池中执行。该函数接受一个函数指针或lambda表达式作为参数,用于指定要执行的任务。同时,我们还可以通过该函数的返回值来获取任务的执行结果。 在通信任务中,我们可以使用QtQTcpSocket类来进行TCP通信操作。比如,可以使用QTcpSocket的connectToHost()函数来连接到服务器,使用write()函数来发送数据,使用read()函数来接收数据等等。 通过使用线程池,我们可以将通信任务分配给多个线程同时处理,提高了程序的并发性能。同时,线程池还可以根据系统资源的使用情况动态调整线程数量,以避免资源浪费和程序性能下降。 总之,通过在Qt中使用线程池来处理TCP通信,可以提高程序的性能和并发能力,同时还可以更好地利用系统资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值