# Tcp ​ Qt中将TCP套接字分为两类:QTcpServer和QTcpSocket,分别对应对服务端和客户端。 ## QTcpServer ​ QTcpServer继承于QObject,所有函数均为`可重入`的。最常用的几个函数为: 1. listen(address = QHostAddress::Any, port = 0)。用于监听一个特定的ip和端口。 2. newConnection()。信号:当有新的连接请求时发射此信号。 3. QTcpSocket * nextPendingConnection()。获取下一个待处理的连接请求。 4. close()。释放程序占用的端口。 下面以程序监听`localhost::22`: ```c++ #include #include class ServerTcp : public QWidget { Q_OBJECT public: ServerTcp(QWidget *parent = nullptr); ~ServerTcp(); private: QString h5Body{ "

Server Successful!

" }; 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(); } ``` 使用浏览器访问: ![1559647560313](assets/1559647560313.png) ### QTcpServer成员函数 #### 信号 ![1559647747445](assets/1559647747445.png) ## 公有函数 ![1559647785238](assets/1559647785238.png) #### 静态公有函数 ![1559647813531](assets/1559647813531.png) #### 保护函数 ![1559647854391](assets/1559647854391.png) ## QTcpSocket ​ 与QTcpServer不同的是,QTcp的继承图为:QObject-->QIODevice-->QAbstractSocket。因此,可以作用与QIODevice的函数(比如QTextStream)同样可以用于QTcpSocket。 ​ QTcpSocket分为两种: 1. 客户端的QTcpSocket。使用bind()绑定一个本地的ip与端口号用于与服务器进行交互,储存有bind的ip和端口号。 2. 服务器使用`nextPendingConnection()`获取的QTcpSocket对象,储存有客户端的ip和端口号。 QTcpSocket是对其父类QAbstractSocket接口的实现,本身没有添加新函数。QTcpSocket使用 - QAbstractSocket::disconnectFromHost()。尝试关闭连接,挂起任务等待至完成。 - QAbstractSocket::close()。关闭IO设备并调用disconnectFromHost()关闭socket连接。 - QAbstractSocket::abort()。强制关闭一个连接。挂起任务被中止。 ### 本地客户端的QTcpSocket 1. bind()。绑定一个指定主机地址和端口。 2. connectToHost()。连接到指定主机或网站,需指定端口号。 3. localAddress()。返回一个QHostAddress,代表QTcpSocket(绑定/连接)的主机。 4. localPort()。返回一个quint16。代表QTcpSocket(绑定/连接)主机的端口。 5. peerName()。返回由connectToHost()指定的主机名或网址。 ### 服务器获取的QTcpSocket 1. peerAddress()。返回客户端的IP地址。 2. peerPort()。返回客户端的端口号。 3. 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”)`。服务器接到请求后,向我们发送相关内容。待套接字可读时读出即可: ```c++ 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()<sock->readAll(); }); ``` 输出内容如下: ```http "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 ... \r\n" ``` ​ 可以看到,接受数据的开始就是`header`,html信息紧跟其后。 ## 参考 [网络常用端口号大全](https://www.cnblogs.com/1666818961-lxj/p/7210021.html)