一. socket
-
socket抽象层 socket抽象层以下包括socket抽象层都是操作系统封装好的 除非你是系统开发工程师,所以一般的软件开发工程都是使用socket提供的接口结合应用层的协议开发应用程序,常见的应用层协议像是HTTP、HTTPS用于web开发,MQTT用于物联网设备间的通信
二. Qt中的TCP通信实现
2.1 网络相关的类
2.2 Qt中的TCP客户端编程
-
对于QTcpSocket可以看成一种Qt中的IO设备,按照常规的IO操作方式读写网络数据即可 -
QTcpSocket的使用方法 connectToHost()
write()/read()
close()
-
同步编程的方式,即面向过程的编程方式 -
代码实现 QTcpSocket client;
char buf[256] = {0};
client.connectToHost("127.0.0.1", 8080);
qDebug() << "Connected:" << client.waitForConnected();
while(1){
qDebug() << "Send Bytes:" << client.write("ALoHa Andrea");
qDebug() << "Send Status:" << client.waitForBytesWritten();
qDebug() << "Data Available:" << client.waitForReadyRead();
qDebug() << "Received Bytes:" << client.read(buf, sizeof(buf)-1);
qDebug() << "Received Data:" << buf;
}
client.close();
-
实验现象
2.3 使用面向对象的思想实现TCP客户端
-
关键的信号 connected() :成功连接服务器
disconnected():远端主机段考连接
readyRead():远端数据到达本机
bytesWritten(qint64):数据成功发送至系统
-
代码 #ifndef CLIENT_H
#define CLIENT_H
#include <QObject>
#include <QTcpSocket>
class ClientDemo : public QObject
{
Q_OBJECT
QTcpSocket m_client;
protected slots:
void onConnected();
void onDisconnected();
void onDataReady();
void onBytesWritten(qint64 bytes);
public:
ClientDemo(QObject* parent = NULL);
void connectTo(QString ip, int port);
qint64 send(const char* data, int len);
qint64 available();
void close();
};
#endif
#include "Client.h"
#include <QHostAddress>
#include <QDebug>
ClientDemo::ClientDemo(QObject* parent) : QObject(parent)
{
connect(&m_client, SIGNAL(connected()), this, SLOT(onConnected()));
connect(&m_client, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
connect(&m_client, SIGNAL(readyRead()), this, SLOT(onDataReady()));
connect(&m_client, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
}
void ClientDemo::onConnected()
{
qDebug() << "onConnected";
qDebug() << "Local Address:" << m_client.localAddress();
qDebug() << "Local Port:" << m_client.localPort();
}
void ClientDemo::onDisconnected()
{
qDebug() << "onDisconnected";
}
void ClientDemo::onDataReady()
{
char buf[256] = {0};
qDebug() << "onDataReady:" << m_client.read(buf, sizeof(buf)-1);
qDebug() << "Data:" << buf;
}
void ClientDemo::onBytesWritten(qint64 bytes)
{
qDebug() << "onBytesWritten:" << bytes;
}
void ClientDemo::connectTo(QString ip, int port)
{
m_client.connectToHost(ip, port);
}
qint64 ClientDemo::send(const char* data, int len)
{
return m_client.write(data, len);
}
qint64 ClientDemo::available()
{
return m_client.bytesAvailable();
}
void ClientDemo::close()
{
m_client.close();
}
2.4 TCP服务器的实现
-
服务器的概念 服务器端是为客户端提供服务的,服务的内容诸如向客户端提供资源,保存客户端数据,为客户端提供功能接口等 -
C/S架构 服务端被动接受连接(服务端无法主动连接客户端) 服务端必须公开网络地址(容易受到攻击) 在职责上:客户端倾向于处理用户交互及体验(GUI) 在职责上:服务器倾向于用户数据的组织和存储(数据处理) -
B/S架构 是一种特殊的C/S网络架构 B/S中的客户端统一使用浏览器(意味着不用安装客户端,只要有浏览器就可以访问服务器) B/S中的客户端GUI通常采用HTML进行开发 B/S中的客户端与服务端通常采用http协议进行通信 -
Qt中的TCP服务端使用的类(QTcpServer) -
QTcpServer使用方式 listen() //监听本机地址的端口
newConnection() //通过信号通知客户端连接
nextPendingConnection()//获取QTcpSocket通信对象
close() //停止监听
-
QTcpServer使用的注意事项 QTcpServer对象不具备通信的能力,它就像一个前台,当有客户端申请连接,会生成一个QTcpSocket对象与客户端进行通信,这个过程类似于Linux下accep()函数的返回值 -
Client/Server交互流程 -
代码 #ifndef SERVERDEMO_H
#define SERVERDEMO_H
#include <QObject>
#include <QTcpServer>
class ServerDemo : public QObject
{
Q_OBJECT
QTcpServer m_server;
public:
ServerDemo(QObject* parent = NULL);
bool start(int port);
void stop();
~ServerDemo();
protected slots:
void onNewConnection();
void onConnected();
void onDisconnected();
void onDataReady();
void onBytesWritten(qint64 bytes);
};
#endif
#include "TcpServer.h"
#include <QHostAddress>
#include <QTcpSocket>
#include <QObjectList>
#include <QDebug>
ServerDemo::ServerDemo(QObject* parent) : QObject(parent)
{
connect(&m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
}
void ServerDemo::onNewConnection()
{
qDebug() << "onNewConnection";
QTcpSocket* tcp = m_server.nextPendingConnection();
connect(tcp, SIGNAL(connected()), this, SLOT(onConnected()));
connect(tcp, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
connect(tcp, SIGNAL(readyRead()), this, SLOT(onDataReady()));
connect(tcp, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
}
void ServerDemo::onConnected()
{
QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(sender());
if( tcp != NULL )
{
qDebug() << "onConnected";
qDebug() << "Local Address:" << tcp->localAddress();
qDebug() << "Local Port:" << tcp->localPort();
}
}
void ServerDemo::onDisconnected()
{
qDebug() << "onDisconnected";
}
void ServerDemo::onDataReady()
{
QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(sender());
char buf[256] = {0};
if( tcp != NULL )
{
qDebug() << "onDataReady:" << tcp->read(buf, sizeof(buf)-1);
qDebug() << "Data:" << buf;
}
}
void ServerDemo::onBytesWritten(qint64 bytes)
{
qDebug() << "onBytesWritten:" << bytes;
}
bool ServerDemo::start(int port)
{
bool ret = true;
if( !m_server.isListening() )
{
ret = m_server.listen(QHostAddress("127.0.0.1"), port);
}
return ret;
}
void ServerDemo::stop()
{
if( m_server.isListening() )
{
m_server.close();
}
}
ServerDemo::~ServerDemo()
{
const QObjectList& list = m_server.children();
for(int i=0; i<list.length(); i++)
{
QTcpSocket* tcp = dynamic_cast<QTcpSocket*>(list[i]);
if( tcp != NULL )
{
tcp->close();
}
}
}
-
实现效果
|