网络接口信息获取
QNetwork提供QHostInfo类提供的静态函数,进行主机名的查找,使用OS提供的查找机制获取一个与主机名关联的IP地址或者
获取一个IP地址关联的主机名
QHostInfo中的静态函数fromName(会阻塞并返回QHostInfo一个对象,这个对象的address函数可以获取其主机的IP地址列表)
与lookupHost(异步获取,每找到主机就会发送信号)可以进行主机信息的获取
//QHostInfo 获取主机名查找
QString localHostName = QHostInfo::localHostName();//获取了本地主机名
//通过获取主机名 然后两种方式获取其IP地址
//fromName 寻找主机信息
QHostInfo info = QHostInfo::fromName(localHostName);
info.addresses();//获取与主机名相关的IP地址列表 包含了ipv4与ipv6
//lookupHost查找IP地址
QHostInfo::lookupHost(localHostName, this, SLOT(lookedUp(QHostInfo)));
void MainWindow::lookedUp(const QHostInfo &host) //对应的槽函数
{
if (host.error() != QHostInfo::NoError) { //先判断是否出错
qDebug() << "Lookup failed:" << host.errorString();
return;
}
foreach (const QHostAddress &address, host.addresses()) //获取地址
qDebug() << "Found address:" << address.toString();
}
Qt网络模块中还提供了QNetworkInterface类获取主机的IP地址列表和网络接口信息。
QNetworkInterface类代表了运行当前程序的主机的网络接口。
// 获取所有网络接口的列表
QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
// 遍历每一个网络接口
foreach (QNetworkInterface interface, list)
{
// 接口名称
qDebug() << "Name: " << interface.name();
// 硬件地址
qDebug() << "HardwareAddress: " << interface.hardwareAddress();
//可以通过它获取所有ip地址
qDebug()<< "Ip address"< // 获取IP地址条目列表,每个条目中包含一个IP地址,一个子网掩码和一个广播地址QList<QNetworkAddressEntry> entryList = interface.addressEntries();//addressEntries()可以返回一个QNetworkAddressEntry对象的列表//QNetworkAddressEntry类保存了一个网络支持的IP 以及该IP地址相关的子网掩码和广播地址// 遍历每一个IP地址条目foreach (QNetworkAddressEntry entry, entryList){
// IP地址qDebug() << "IP Address: " << entry.ip().toString();// 子网掩码qDebug() << "Netmask: " << entry.netmask().toString();// 广播地址qDebug() << "Broadcast: " << entry.broadcast().toString();}
}
UDP
Socket"套接字"简单来说:一个IP地址,加一个port端口号。
其中IP地址指定了网络中的一台主机,而端口号指定了该主机上的一个网络程序,这样使用套接字就可以实现网络上两台主机上的两个应用程序之间的通信。
UDP(用户数据报协议)是一个轻量级、不可靠、面向数据的、无连接的协议。一般分为发送端与接收端
发送端
QUdpSocket *sender;sender = new QUdpSocket(this);
QByteArray datagram = "hello world!";sender->writeDatagram(datagram.data(), datagram.size(),QHostAddress::Broadcast, 45454); //广播地址 端口号//参数分别为: 数据,数据长度,主机地址,端口号为address的主机的port端口//意义是发送size大小的数据包data到地址//不建议发送大于512字节的数据报;端口号最好取1024以上的,最大为65535 2的16次方
接收端
QUdpSocket *sender;receiver = new QUdpSocket(this);receiver->bind(45454, QUdpSocket::ShareAddress);//和发送端端口号一致 不需指定IP。默认支持所有IPV4,绑定模式表明允许其他服务器//每当有数据报来时,都会触发readyRead()connect(receiver, SIGNAL(readyRead()), this, SLOT(processPendingDatagram()));
// 处理等待的数据报void Receiver::processPendingDatagram(){// 拥有等待的数据报while(receiver->hasPendingDatagrams()) //hasPendingDatagrams()判断是否还有等待的数据报{
QByteArray datagram;// 让datagram的大小为等待处理的数据报的大小,这样才能接收到完整的数据datagram.resize(receiver->pendingDatagramSize());//pendingDatagramSize() 当前数据包大小// 接收数据报,将其存放到datagram中receiver->readDatagram(datagram.data(), datagram.size());//readDatagram将不大于指定长度的数据保存到datagram.data()ui->label->setText(datagram);}
}
TCP (HTTP与FTP都是基于TCP的)
服务器端 如果客户端连接发送信号
客服端 如果连接上服务器发送信号
TCP(传输控制协议)用于数据传输的底层网络协议,多个互联网协议(HTTP与FTP都是基于TCP的)。TCP是一个面向数据流和连接的可靠传输协议。TCP传输的是连续的数据流
TCP编程分为客户端与服务器端,也就是所谓的C/S模型
TCP编程中
QTcpSocket中的成员函数
peerAddress();//获取IP地址 peer指用TCP协议连接在一起的主机的通称
peerName(); //获取名称
peerPort();//获取端口号
read()和write()//进行读写
bytesAvailable()//度数据之前,确保里面有数据
关联connect(Socket, SIGNAL(readyRead()), this, SLOT(readMessage())); 当有数据发送过来指定的套接字,便执行槽函数
发送数据时一定要最开始写入实际数据大小信息(占两个字节) 用quint16表示close();套接字的关闭/服务器的关闭
服务器端
通过tcpServer->listen(主机IP地址,端口号)绑定主机
关联connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendMessage()));
有客服端连接就会发送newConnection()信号,然后在槽函数中通过QTcpSocket *clientConnection = tcpServer-
>nextPendingConnection();获取与客户端连接的套接字
关联connect(clientConnection, SIGNAL(disconnected()),clientConnection, SLOT(deleteLater()));//连接断开时 删除套接字
如果服务器端发送了数据就要进行 套接字的去除
客户端套接字断开时会发送disconnected(),disconnectFromHost() 函数会一直等待套接字将所有数据发送完毕,然后关闭,
并发送disconnect信号。
tcpSocket.waitForDisconnected();//等待知道套接字发送disconnect信号
QTcpServer *tcpServer;tcpServer = new QTcpServer(this);// 使用了IPv4的本地主机地址,等价于QHostAddress("127.0.0.1")if (!tcpServer->listen(QHostAddress::LocalHost, 6666)) {qDebug() << tcpServer->errorString();close();
}
//每当有客户端连接时,服务器就会发送newConnection()信号connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendMessage()));服务器端发送数据// 用于暂存我们要发送的数据QByteArray block;// 获取已经建立的连接的套接字QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); //nextPendingConnection()获取连接的套接字connect(clientConnection, SIGNAL(disconnected()), //连接断开时 删除套接字clientConnection, SLOT(deleteLater()));clientConnection->write(block);
clientConnection->disconnectFromHost();//disconnectFromHost() 函数会一直等待套接字将所有数据发送完毕,然后关闭,并发送disconnect信号客户端abort();//取消已有的连接
通过tcpSocket->connectToHost(主机IP地址,端口号)请求主机
关联connect(tcpClient, SIGNAL(connected()), this, SLOT(startTransfer()));
当连接好主机后,主机会发送connected()信号,然后执行槽函数
QTcpSocket *tcpSocket;tcpSocket = new QTcpSocket(this);connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage())); //当有可读数据发射connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), //当有发生错误this, SLOT(displayError(QAbstractSocket::SocketError)));
// 取消已有的连接tcpSocket->abort();//调用connectToHost()函数连接到指定主机的指定端口。tcpSocket->connectToHost(ui->hostLineEdit->text(),ui->portLineEdit->text().toInt());客服端接收数据
接收数据时一般前两2个字节是整个数据的大小信息
// 用来存放数据的大小信息quint16 blockSize;
QDataStream in(tcpSocket);// 设置数据流版本,这里要和服务器端相同in.setVersion(QDataStream::Qt_4_6);// 如果是刚开始接收数据if (blockSize == 0) {//判断接收的数据是否大于两字节,也就是文件的大小信息所占的空间//如果是则保存到blockSize变量中,否则直接返回,继续接收数据if(tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return;in >> blockSize;}
// 如果没有得到全部的数据,则返回,继续接收数据if(tcpSocket->bytesAvailable() < blockSize) return;// 将接收到的数据存放到变量中in >> message;获取连接主机的信息
qDebug() << tcpSocket->peerAddress();//获取IP地址 peer指用TCP协议连接在一起的主机的通称qDebug() <<tcpSocket->peerName(); //获取名称qDebug() << tcpSocket->peerPort();//获取端口号
提供简单的代码:完成了网络接口的获取,UDP简单编程,TCP简单编程(服务器发数据,客户端接收)