我们首先复习一下TCP通信的流程
基于linuxTCP客户端和服务器
QT下的TCP处理流程
服务器先启动(处于监听状态)
各函数的意义和使用
-
QTcpServer Class
*
QTcpServer
*类提供了一个基于TCP的服务器。这个类可以接受传入的TCP连接。您可以指定端口或让QTcpServer自动选择一个端口。您可以收听特定地址或所有机器的地址。调用listen()让服务器侦听传入的连接。每次客户端连接到服务器时,都会发出newConnection()
信号。 -
QTcpSocket Class
QTcpSocket
类提供了一个TCP套接字。TCP(传输控制协议)是一种可靠的,面向流的,面向连接的传输协议。 它特别适合连续传输数据。QTcpSocket
是QAbstractSocket
的一个方便的子类,它允许你建立一个TCP连接并传输数据流。- 服务器端以监听的方式监听listen()客户端是否有连接请求
- 客户端以调用**
connectToHost()
**函数主动连接服务器端
-
listen():Qt中,服务端的监听套接字不再是socket,而是
QTcpServer
和QTcpSocket
。此外,它将绑定bind()和监听listen()合为一个函数,即监听listen(),在调用的同时指定主机地址和端口号。 -
connectToHost()
【客户端】
而客户端的通信套接字也不再是socket,而是QTcpSocket
,连接也不是connect(),而是connectToHost()
,意为主动向主机(服务端)发起连接。 -
newConnection()
【服务端】
如果客户端发起连接并且成功,服务端将会收到一个信号。在Qt中,服务端不再是由accept()来确定连接的建立,而是会触发一个newConnection
信号。既然是信号,就要有与之对应的槽函数。槽函数中主要的工作是取出建立好的套接字QTcpSocket
(它是真正的通信套接字)。 -
write()
【服务端/客户端】
客户端用write()发送数据,如果数据传送成功,对方的通信套接字会触发readyRead()
信号(继承自QIODevice
类的信号),说明可以开始读数据了,我们需要在对应的槽函数中做接收处理。反过来,服务端给客户端发信息也是一样的。 -
connected() & disconnected()
【服务端/客户端】
只要成功与对方建立连接,无论是服务端还是客户端,通信套接字都会自动触发 -
**
connected()
**信号,而如果对方主动断开连接,通信套接字会自动触发disconnected()信号,我们可以利用这两个信号作出一些提示,比如在客户端与服务器端成功连接后,在客户端窗口输出“已成功连接服务器!”或者“已与服务器断开连接!”。
添加TCP模块
#include <QTcpServer>
#include <QTcpSocket>
client.h/server.h
#include <QTcpSocket>
...
class Client : public QWidget
{
...
private:
Ui::Client *ui;
QTcpSocket *client_chat;
-------------------------------------
#include <QTcpSocket>
#include <QTcpServer>
#include <QPushButton>
....
class Server : public QWidget
{
....
private:
Ui::Server *ui;
QTcpServer *watch;//监听
QTcpSocket *chat; //通信
};
#endif // SERVER_H
client.cpp
#include "client.h"
#include "ui_client.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
Client::Client(QWidget *parent) :
QWidget(parent),
ui(new Ui::Client)
{
ui->setupUi(this);
ui->sIP->setText("127.0.0.1");
ui->sPort->setText("8000");
client_chat = new QTcpSocket(this);
client_chat->connectToHost(QHostAddress(ui->sIP->text()),8000);
connect(client_chat,&QTcpSocket::readyRead,this,[=](){
qDebug()<<1;
QByteArray qba2 = client_chat->readAll();
ui->record->append("对方说"+qba2);
});
connect(ui->send,&QPushButton::clicked,this,[=](){
client_chat->write(ui->input->toPlainText().toUtf8());
ui->record->append("Me say:"+ui->input->toPlainText());
ui->input->clear();
});
}
server.cpp
#include "server.h"
#include "ui_server.h"
#include <QDebug>
Server::Server(QWidget *parent) :
QWidget(parent),
ui(new Ui::Server)
{
ui->setupUi(this);
ui->sIP->setText("127.0.0.1");
ui->sPort->setText("8000");
watch = new QTcpServer(this);
//这里类型转换有点问题,因此我直接写8000
watch->listen(QHostAddress(ui->sIP->text()),8000);
connect(watch,&QTcpServer::newConnection,this,[=](){
chat = watch->nextPendingConnection();
ui->record->append("有新的连接");
QList<QTcpSocket*>socketList;
socketList.append(chat);
QString IP= chat->peerAddress().toString();
quint16 PORT = chat->peerPort();
qDebug()<<socketList;
qDebug()<<IP<<PORT;
connect(chat,&QTcpSocket::readyRead,this,[=](){
QByteArray qba = chat->readAll();
ui->record->append("对方说:"+qba);
});
});
connect(ui->send,&QPushButton::clicked,this,[=](){
chat->write(ui->input->toPlainText().toUtf8());
ui->record->append("MeSay:"+ui->input->toPlainText());
ui->input->clear();
});
}
main.c
#include "server.h"
#include "client.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Server w;
w.show();
Client c;
c.setWindowTitle("客户端");
c.show();
return a.exec();
}