Tcp
Qt中将TCP套接字分为两类:QTcpServer和QTcpSocket,分别对应对服务端和客户端。
QTcpServer
QTcpServer继承于QObject,所有函数均为可重入的。最常用的几个函数为:
listen(address = QHostAddress::Any, port = 0)。用于监听一个特定的ip和端口。
newConnection()。信号:当有新的连接请求时发射此信号。
QTcpSocket * nextPendingConnection()。获取下一个待处理的连接请求。
close()。释放程序占用的端口。
下面以程序监听localhost::22:
#include <QTcpServer>
#include <QTcpSocket>
class ServerTcp : public QWidget
{
Q_OBJECT
public:
ServerTcp(QWidget *parent = nullptr);
~ServerTcp();
private:
QString h5Body{
"<h1>Server Successful!</h1>"
};
QTcpServer*ser=new QTcpServer(this);
};
// 构造函数
ServerTcp::ServerTcp(QWidget *parent)
: QWidget(parent)
{
ser->listen(QHostAddress::LocalHost,22);
connect(ser,&QTcpServer::newConnection,[=](){
QTcpSocket *sock=ser->nextPendingConnection();
sock->write(this->h5Body.toStdString().c_str());
sock->waitForBytesWritten();
sock->close();
});
}
// 析构函数
ServerTcp::~ServerTcp()
{
ser->close();
}
使用浏览器访问:

QTcpServer成员函数
信号

公有函数

静态公有函数

保护函数

QTcpSocket
与QTcpServer不同的是,QTcp的继承图为:QObject–>QIODevice–>QAbstractSocket。因此,可以作用与QIODevice的函数(比如QTextStream)同样可以用于QTcpSocket。
QTcpSocket分为两种:
客户端的QTcpSocket。使用bind()绑定一个本地的ip与端口号用于与服务器进行交互,储存有bind的ip和端口号。
服务器使用
nextPendingConnection()获取的QTcpSocket对象,储存有客户端的ip和端口号。QTcpSocket是对其父类QAbstractSocket接口的实现,本身没有添加新函数。QTcpSocket使用
QAbstractSocket::disconnectFromHost()。尝试关闭连接,挂起任务等待至完成。
QAbstractSocket::close()。关闭IO设备并调用disconnectFromHost()关闭socket连接。
QAbstractSocket::abort()。强制关闭一个连接。挂起任务被中止。
本地客户端的QTcpSocket
bind()。绑定一个指定主机地址和端口。
connectToHost()。连接到指定主机或网站,需指定端口号。
localAddress()。返回一个QHostAddress,代表QTcpSocket(绑定/连接)的主机。
localPort()。返回一个quint16。代表QTcpSocket(绑定/连接)主机的端口。
peerName()。返回由connectToHost()指定的主机名或网址。
服务器获取的QTcpSocket
peerAddress()。返回客户端的IP地址。
peerPort()。返回客户端的端口号。
write()。向客户端写入数据。
使用QTcpSocket连接网站
本例以百度(www.baidu.com)为例。要连接网站,还需要知道网页的端口号:
| 端口 | 协议类型 | 协议实现 | 中文名 | | :–: | :——: | :——: | :————————————–: | | 21 | tcp | FTP | 文件传输协议 | | 22 | tcp | SSH | 安全登录、文件传送(SCP)和端口重定向 | | 23 | tcp | Telnet | 不安全的文本传送 | | 25 | tcp | SMTP | Simple Mail Transfer Protocol (E-mail) | | 69 | udp | TFTP | Trivial File Transfer Protocol | | 79 | tcp | finger | Finger | | 80 | tcp | HTTP | 超文本传送协议 (WWW) | | 88 | tcp | Kerberos | Authenticating agent | | 110 | tcp | POP | Post Office Protocol (E-mail) | | 113 | tcp | ident | old identification server system | | 119 | tcp | NNTP | used for usenet newsgroups | | 220 | tcp | IMAP | | | 443 | tcp | HTTPS | used for securely transferring web pages |
我们要连接的是网站,也就是说HTTP(80)。先看一下连接流程:
首先使用connectToHost()连接网站,连接完成后发送GET请求(“GET / HTTP/1.1\r\n\r\n”)。服务器接到请求后,向我们发送相关内容。待套接字可读时读出即可:
QTcpSocket *sock=new QTcpSocket(this);
sock->connectToHost("www.baidu.com",80);
connect(sock,&QAbstractSocket::connected,[this](){
this->sock->write("GET / HTTP/1.1\r\n\r\n");
});
connect(sock,&QAbstractSocket::readyRead,[this](){
qDebug()<<this->sock->readAll();
});
输出内容如下:
"HTTP/1.1 200 OK\r\nAccept-Ranges: bytes\r\nCache-Control: no-cache\r\nConnection: Keep-Alive\r\nContent-Length: 14615\r\nContent-Type: text/html\r\nDate: Tue, 04 Jun 2019 15:15:24 GMT\r\nEtag: \"5cf609dc-3917\"\r\nLast-Modified: Tue, 04 Jun 2019 06:04:12 GMT\r\nP3p: CP=\" OTI DSP COR IVA OUR IND COM \"\r\nPragma: no-cache\r\nServer: BWS/1.1\r\nSet-Cookie: BAIDUID=F2D7E5B7387A5370555556903159EBB8:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com\r\nSet-Cookie: BIDUPSID=F2D7E5B7387A5370555556903159EBB8; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com\r\nSet-Cookie: PSTM=1559661324; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com\r\nVary: Accept-Encoding\r\nX-Ua-Compatible: IE=Edge,chrome=1\r\n\r\n
<!DOCTYPE html>
...
</html>\r\n"
可以看到,接受数据的开始就是header,html信息紧跟其后。