QT入门学习之TCP

1、TCP简介

TCP是一个用于数据传输的低层的网络通信协议,HTTP、TCP这些互联网协议都是基于TCP协议的。TCP是一个面向数据流和链接的可靠传输协议。QTcpSocket类为TCP提供了一个接口,该类也继承自QAbstractSocket。可以使用QTcpSocket来实现POP3、SMTP、NNTP等标准的网络协议,也可以实现自定义的网络协议。与QUdpSocket传输的数据包不同,QTcpSocket传输是连续的数据流,他尤其适合于连续的数据传输。TCP编程一般分为客户端和服务器端也就是C/S模型。

2、TCP编程

(1)、在任何数据传输之前,都必须建立一个TCP连接到远程的主机和端口上,一旦连接被建立,主机(使用TCP协议连接在一起的主机统称为peer)的IP地址和端口可以分别使用。QTcpSocket::peerAddress()和QTcpSocket::peerPort()来获取。在任何时间,peer都可以关闭连接,这时候数据传输就会立即停止。

(2)QTcpSocket是异步进行工作的,需要通过发射信号来报告状态改变和错误信息。可以使用QTcpSocket::write()来写数据,使用QTcpSocket::read()来读数据。QTcpSocket代表了两个独立的数据流:一个用来读出,一个用来写入。因为QTcpSocket继承于QIODevice,所以可以用QTextStream和QDataStream。当一个从一个QTcpSocket中读取数据之前,必须先调用QTcpSocket::bytesAvailable()函数来确保已经有足够的数据可用。

(3)如何处理到来的TCP连接?
处理到来的TCP连接一般发生在服务器端的应用程序中,可以使用QTcpServer类。调用listen()来设置服务器,然后关联newConnection()信号,每当客户端连接时候都会发射该信号,在槽函数中调用nextPendingConnection()来接收这个连接,然后使用该函数返回的QTcpSocket对象与客户端进行通信。

(4)虽然QTcpSocket大部分的函数都是一部工作的,其实QTcpSocket也可以实现同步工作(如:阻塞),调用QTcpSocket的以waitfor开头的函数,他们会挂起调用的线程,直到一个信号被发射。如:在调用QTcpSocket::connectToHost()非阻塞函数后,调用QTCPSocket::waitforConnected()来阻塞线程,直到connected()信号被发射。使用waitfor函数阻塞时事件将不会被处理,如果一个GUI线程中,用户界面就会出现冻结现象,所有一般建议不再GUI线程中使用同步套接字。

3、TCP编程实现发送一个字符串

例程功能:服务器一直监听一个端口,一旦有客户端连接请求,便建立连接,并向客户端发送一个字符串,然后客户端接收该字符串并显示出来。
服务器端:

//初始化服务器
QTcpServer  *tcpServer=new QTcpServer(this);
if(!tcpServer->listern(QHostAddress::LocalHost,6666))//使用了IPv4的本地主机地址
{
 	qDebug()<<tcpServer->errorString();
 	Close();
}

//一旦服务器监听到新的请求连接信号,服务器就会发射相应的数据到客户端
Connect(tcpServer,&QTcpServer::newConnection,this,&Server::sendMessage);

 Void Server::sendMessage()
  {
	QByteArray block;//用于暂存要发送的数据
	QDataStream out(&block,QIODevice::WriteOnly);//创建数据流
	Out.setVersion(QDataStream::Qt_5_8);//设置数据流版本,客户端和服务器端必需使	用一样的数据流版本
	out.<<(qint16)0;//为数据流前两个字节赋值为0
	out<<”hello world!!!”;//为数据流赋值(带传输的字符串)
	out.device()->seek(0);//跳转到数据流最前面位置
	out<<(qint16)(block.size()-sizeof(qint16));//为数据流最前面的两个字节赋值要传输的字符串字节数
	QTcpSocket *clientConnection=tcpServer->nextPendingConnection();//获取已经建立的链接的套接字
	Connect(clientConnection,&QTcpSocket::disconnection,clientConnection,&QTcpSocket::deleteLater);//关联disconnection信号和deleteLater槽函数,当断开时删除套接字
	clientConnection->write(block);//发射字符串
	clientConnection->disconnectFromHost();//断开连接而调用disconnectFromHost()函数会一直等待套接字将所有数据发送完毕,然后关闭该套接字,并发射disconnected()信号。 
}

客户端:
初始化:
QTcpSocket *tcpSocket = new QTcpSocket(this);
connect(tcpSocket, &QTcpSocket::readyRead, this, &Client::readMessage);
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),this,
SLOT(displayError(QAbstractSocket::SocketError))); 

连接按键槽函数:
blockSize = 0; // 初始化数据大小信息为0
tcpSocket->abort(); // 取消已有的连接
tcpSocket->connectToHost(ui->hostLineEdit->text(), ui->portLineEdit->text().toInt()); 

读取数据的槽:
void Client::readMessage()
{
	QDataStream in(tcpSocket);//创建数据流
	in.setVersion(QDataStream::Qt_5_8); // 设置数据流版本,这里要和服务器端相同
	if (blockSize == 0) { // 如果是刚开始接收数据
	//判断接收的数据是否大于两字节,也就是文件的大小信息所占的空间
	//如果是则保存到blockSize变量中,否则直接返回,继续接收数据
	if(tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return;
	in >> blockSize;
} 
	if(tcpSocket->bytesAvailable() < blockSize) return; // 如果没有得到全部的数据,则	返回,继续接收数据
	in >> message; // 将接收到的数据存放到变量中
	ui->messageLabel->setText(message); // 显示接收到的数据
} 

Note :TCP编程实现传输一个文件与之类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值