在介绍网络编程之前,先介绍几个相关的类。
1.QAbstractSocket
该类提供了所有socket类型所共有的基本函数,是QTcpSocket和QUdpSocket的基类,该类包含了这两个类所共有的成员函数。如果你需要一个套接字,你有两种选择:
1.实例化QTCpSocket或者QUdpSocket
2.创建一个本地的socket描述符,实例化QAbstractSocket,然后调用setSocketDescriptor()函数去包裹一个本地套接字
这个类尽可能的联合了TCP和UDP的差别,尽管UDP是不可靠的连接,但是connectToHost()为UDP建立了一个假的连接,使其步骤尽量与TCP协议相似。在本质上QAbstractSocket记住了传递给connectToHost()的ip地址和端口号,而QAbstratSocket中的成员函数 read和write将会使用这些值,不过在使用时我们无需关心这些内部实现。
无论在什么时候QAbstractSocket都有一个状态,而我们可以通过调用成员函数state()返回这个状态,初始的状态是 UnconnectedState,当程序调用了connectToHost()之后,QAbstractSocket的状态会变成HostLookupState,如果主机被找到,QAbstaractSocket进入connectingState状态并且发射HostFound()信号,当连接被建立的时候QAbstractSocket 进入了connectedState状态 并且发射connected()信号,如果再这些阶段出现了错误,QAbstractSocket将会发射error()信号,无论在什么时候,如果状态改变了,都会发射stateChanged(),如果套接字准备好了读写数据,isValid()将会返回true。
无论什么时候 QAbstractSocket的状态改变都会发射stateChanged()信号,无论什么时候只要发生了错误,就会发送error()信号。
向套接字里读写数据通过调用 read或者是write函数 ,或者使用reaLline()和readAll()函数。QAbstractSocket从QIODevice继承了以单个字符传送的getChar(),putChar()和ungetChar()函数。当数据被写进套接字后会发射bytesWritten()信号。需要注意的是,qt没有限制写缓冲区的大小,因此我们可以监听这个信号,以此来获得写缓冲区的大小。
当一块数据到达时候,readRead()信号将会被发送,通过调用bytesAliable()函数可以得到可读的数量,因此我们可以连接readRead()信号到槽,以此来读取数据,如果不一次读取完毕,剩下的数据还是有效的。如果要限制读缓冲区可以调用 setReadBufferSize()。
关闭一个连接可以调用disconnectFromHost(),这个时候QAbstractSocket会进入closingstate状态,当将数据全部发送完之后,QAbstaractSocket会进入closedState状态,并且发送disconnected()信号。如果想要立即终止连接而不顾当前正在传输的数据,可以调用abort(),如果远程主机断开连接,QAbstractSocket会发射 error(QAbstractSocket::RemoteHostClosedError(),同时socket的状态仍然为ConnectedState,然后发射disconnected()信号。
而对于每个连接我们可以通过调用 peerPort() 、peerAddress()、 peerName() 返回每个连接的名字,地址,端口,而我们可以通过调用localPort()和localAddress返回本地端口和地址。
QAbstractSocket提供了一套函数用于挂起调用线程直到特定的信号被发射。 这些函数可以被用来实现一个阻塞套接字:
waitForConnected 阻塞直到连接被建立
waitForReadyRead() 阻塞直到新的数据到达
waitForBytesWritten() 阻塞直到数据写入完毕
waitForDisconnected() 阻塞直到连接被关闭。
阻塞套接字的使用例子:
int numRead = 0, numReadTotal = 0;
char buffer[50];
forever {
numRead = socket.read(buffer, 50);
// do whatever with array
numReadTotal += numRead;
if (numRead == 0 && !socket.waitForReadyRead())
break;
}
当连接断开或者错误发生时,
waitForReadyRead()才会返回假。
阻塞套接字应该只用在非GUI线程中,防止用户界面卡死。
This enum describes the different states in which a socket can be.
Constant | Value | Description |
---|---|---|
QAbstractSocket::UnconnectedState | 0 | The socket is not connected. |
QAbstractSocket::HostLookupState | 1 | The socket is performing a host name lookup. |
QAbstractSocket::ConnectingState | 2 | The socket has started establishing a connection. |
QAbstractSocket::ConnectedState | 3 | A connection is established. |
QAbstractSocket::BoundState | 4 | The socket is bound to an address and port (for servers). |
QAbstractSocket::ClosingState | 6 | The socket is about to close (data may still be waiting to be written). |
QAbstractSocket::ListeningState | 5 | For internal use only. |