1.Qt中TCP客户端编程
- 对Qt编程而言,网络只是数据传输的通道;
- Qt提供了QTcpSocket类(封装了TCP协议细节);
- 将QTcpSocket的对象当做黑盒使用,进行数据首发。

1.1QTcpSocket类的继承

1.2QTcpSocket的使用
- 连接服务器主机(connectToHost())
- 发送数据/接受数据(write()/read())
- 关闭连接(close())
1.3QTcpSocket的注意事项
- 默认情况下,QTcpSocket使用异步编程的方式
- 操作完成后立即返回(返回只代表的操作开始,不代表操作的结果,类似C语言中的回调函数以及Qt中的信号和槽机制)
- 通过发送信号的方式返回操作的结果
 
2.QTcpSocket同步编程
2.1QTcpSocket提供辅助函数可完成同步编程的方式(返回值代表返回结果,平时编程使用的大多是同步编程的方式)
- waitForConnected()/waitForDisconnected()
- waitForBytesWritten()/waitForReadyRead()
2.2QTcpSocket同步编程流程
调用完功能函数(如connectToHost)立刻调用对应的同步辅助函数即实现同步编程

2.3QTcpSocket同步编程代码
代码运行时需启动socket的服务程序模拟tcp服务端

#include "clientdemo.h"
#include <QtGui/QApplication>
#include <QTcpSocket>
#include <QDebug>
void SyncClientDemo()
{
	QTcpSocket client;
	char buf[256] = {0};
	client.connectToHost("127.0.0.1", 8080);
	qDebug() << "Connected:" << client.waitForConnected();
	qDebug() << "Send Bytes:" << client.write("D.T.Software");
	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();
	// client.waitForDisconnected();
}
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	SyncClientDemo();
	//ClientDemo w;
	//w.show();
	return a.exec();
}
结果


3.QTcpSocket异步编程
3.1 QTcpSocket的异步编程
- QTcpSocket的对象通过发送信号的方式返回操作结果
- 可以在程序中将对应的信号连接到槽函数,获取结果
- 在GUI应用程序中通常使用QTcpSocket的异步编程方式
3.2QTcpSocket中的关键信号
- connected():成功连接远端主机
- disconnected:远程主机断开连接
- readyRead():远端主机数据到达本机
- bytesWritten(qint64):数据成功发送至系统(OS)
3.3编程实践
clientdemo.h
#ifndef CLIENTDEMO_H
#define CLIENTDEMO_H
#include <QObject>
//#include "ui_clientdemo.h"
#include <QTcpSocket>
class ClientDemo : public QObject
{
	Q_OBJECT
		QTcpSocket m_client;
protected slots:
	void onConnected();
	void onDisconnected();
	void onDataReady();
	void onBytesWritten(qint64 bytes);
public:
	qint64 send(const char* data, int len);
	qint64 available();//得到到达本机的数据长度
	ClientDemo(QObject *parent = NULL);
	void connectToHost(QString ip,int port);
    void close();
	~ClientDemo();
private:
//	Ui::ClientDemoClass ui;
};
#endif // CLIENTDEMO_H
clientdemo.cpp
#include "clientdemo.h"
#include <QDebug>
ClientDemo::ClientDemo(QObject *parent): QObject(parent)
{
	//ui.setupUi(this);
	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::connectToHost(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();
}
ClientDemo::~ClientDemo()
{
	
}
main.cpp
#include "clientdemo.h"
#include <QtGui/QApplication>
#include <QTcpSocket>
#include <QDebug>
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	//SyncClientDemo();
	ClientDemo w;
	w.connectToHost("127.0.0.1",8080);
	char buf[]="abc";
	w.send(buf,sizeof(buf)-1);
	//w.show();
	return a.exec();
}
结果


4.小结
- Qt提供了QTcpSocket类,其对象可用于收发TCP数据
- QTcpSocket默认使用异步编程方式
- QTcpSocket提供辅助函数用于完成同步编程的方式
- GUI应用程序通常使用QTcpSocket的异步编程方式