项目介绍
基于TCP的客户端聊天系统,客户端连接服务器ip成功后,即可与服务器之间通讯。详细说明见下文。
相关知识点
开发工具为QT, 具有网络功能的程序需要在pro文件中添加“QT += network”。
QHostInfo
QHostInfo类为主机名查找提供了静态函数。这个类提供了两个方便的静态函数:一个异步工作并在找到主机时发出信号,另一个阻塞并返回QHostInfo对象。
要异步查找主机的IP地址,调用lookupHost(),它接受主机名或IP地址、接收方对象和槽签名作为参数并返回ID。 您可以通过使用查找ID调用abortHostLookup()来中止查找。
//通过域名查找ip
QHostInfo::lookupHost("www.baidu.com",this,[](const QHostInfo& info)
{
qDebug()<<info.hostName()<<info.addresses();
});
//查找ip是否存在
QHostInfo::lookupHost("183.232.231.172",this,[](const QHostInfo& info)
{
qDebug()<<info.hostName()<<info.addresses();
});
当结果准备好时,将调用该槽。 结果存储在QHostInfo对象中。 调用addresses()获取主机的IP地址列表,调用hostName()获取所查找的主机名。
如果查找失败,error()将返回所发生的错误类型。 errorString()给出了可读的查找错误描述。
要一个阻塞查找,使用QHostInfo::fromName()函数:
QHostInfo info = QHostInfo::fromName("smtp.qq.com");
qDebug()<<info.hostName()<<info.addresses();
QHostAddress
此类以独立于平台和协议的方式保存IPv4或IPv6地址址.
QAbstractSocket
QAbstractSocket类提供了所有套接字类型通用的基本功能 。AbstractSocket是QTcpSocket和QUdpSocket的基类,包含这两个类的所有通用功能。
QTcpSocket
QTcpSocket类提供一个TCP套接字.
QTcpSocket *tcpSocket = new QTcpSocket(this);
tcpSocket->connectToHost("127.0.0.1",8888);
//此信号在调用connectToHost()并成功建立连接后发出。
void connected()
//这个信号在套接字被断开时发出。
void disconnected()
//此信号在发生错误后发出。当发出此信号时,套接字可能还没有准备好重新连接。 在这种情况下,尝试重新连接应该从事件循环中完成。 例如,使用带有0作为超时的QTimer::singleShot()。
void error(QAbstractSocket::SocketError socketError)
//在调用connectToHost()并成功查找主机之后,将发出此信号。
void hostFound()
//每当有新的数据可以从设备的当前读取通道读取时,就会发出此信号。
void readyRead()
QUdpSocket
UDP(用户数据报协议)是一种轻量级、不可靠、面向数据报、无连接的协议。 当可靠性不重要时,可以使用它。 QUdpSocket是QAbstractSocket的一个子类,允许您发送和接收UDP数据报。
使用该类最常见的方法是使用bind()绑定到一个地址和端口,然后调用writeDatagram()和readDatagram() / receiveDatagram()来传输数据。 如果你想使用标准的QIODevice函数read(), readLine(), write()等,你必须首先通过调用connectToHost()将套接字直接连接到对等体。
套接字在每次将数据报写入网络时发出bytesWritten()信号。 如果您只是想发送数据报,则不需要调用bind()。
readyRead()信号在数据报到达时被触发。 在这种情况下,hasPendingDatagrams()返回true。 调用pendingDatagramSize()获取第一个挂起的数据报的大小,并调用readDatagram()或receiveDatagram()读取它。
QTcpServer
QTcpServer类提供了一个基于tcp的服务器。
这个类使接收传入的TCP连接成为可能。 您可以指定端口或让QTcpServer自动选择一个端口。 您可以监听一个特定的地址或所有机器的地址。
调用listen()让服务器监听传入的连接。 然后,每当客户机连接到服务器时,就会发出newConnection()信号。 调用nextPendingConnection()接受挂起的连接作为已连接的QTcpSocket。 该函数返回一个指向QAbstractSocket::ConnectedState中的QTcpSocket的指针,您可以使用该指针与客户端通信。
Server::Server(QObject *parent) : QObject(parent)
{
m_tcpServer = new QTcpServer(this);
m_tcpServer->listen(QHostAddress::Any,6666);
connect(m_tcpServer,&QTcpServer::acceptError,this,&Server::onAcceptError);
connect(m_tcpServer,&QTcpServer::newConnection,this,&Server::onNewConnection);
}
void Server::onAcceptError(QAbstractSocket::SocketError socketErr)
{
qDebug()<<"hasError"<<socketErr;
}
void Server::onNewConnection()
{
qDebug()<<"newConnection";
//获取下一个待处理的连接
QTcpSocket* tcpSocket = m_tcpServer->nextPendingConnection();
m_tcps.push_back(tcpSocket);
tcpSocket->write("hello");
qDebug()<<m_tcps.size();
connect(tcpSocket,&QTcpSocket::readyRead,this,&Server::onReadyRead);
}
void Server::onReadyRead()
{
QTcpSocket *tcpsokcet = dynamic_cast<QTcpSocket*>(sender());
if(tcpsokcet)
{
qDebug() <<"server"<<QHostAddress(tcpsokcet->peerAddress().toIPv4Address()).toString()<<tcpsokcet->peerName()<<tcpsokcet->peerPort();
}
}
常用函数
//服务器开始监听指定addres和port上的连接,有新链接发出newConnection()信号
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
//将下一个挂起的连接作为已连接的QTcpSocket对象返回。 在 newConnection()的槽函数中使用
virtual QTcpSocket *nextPendingConnection()
//当接受新连接导致错误时将发出此信号。 socketError参数描述了发生的错误类型。
[signals] void acceptError(QAbstractSocket::SocketError socketError)
//每当有新连接可用时,就会发出此信号。
[signals] void newConnection()
项目展示
项目代码已上传至博客。博客gitee