您的位置:首页 > 编程语言 > Qt开发

Qt tcp socket编程

2016-06-24 16:20 986 查看
《学习笔记》

QTcpSever用于监听,QTcpSocket用于连接客户端和服务端。

客户端连接服务端很简单,connectToHost(QHostAddress("IP", 666);,填写IP和端口就可以,连接成功后,再关联信号readyRead()就可以读取服务端发送过来的数据了

服务端首先监听某个端口,看是否有连接到该端口的机器,然后获取客户端连接的socket有两种方法:

1:关联信号newConnection(),在接受连接的过程中,应当是有一个队列,等待的连接都将放入连接队列中,在相应的槽函数中通过nextPendingConnection 函数可以得到该socket,进而可以进行通信,通信还是通过readyRead()信号,注意:这种方式返回的socket不可以用于另一个线程

2:另一种方法是继承QTcpSocket类重写incomingConnection (qintptr socketDescriptor) 函数
,再有连接时这个函数会被系统调用,socketDescriptor  为套接字描述符,用这个描述符创建一个socket就可以了,即setSocketDescriptor 
这个函数,描述符传给这个函数参数即可。

下面是我参照网上写的测试代码,可以同时有多个客户端连接到服务的同一个端口进行相互之间通信

服务端:

chatSever.h

#include <QObject>

#include <qtcpserver.h>

#include <QList>

#include <tcpsocket.h>


class chatSever : public QTcpServer

{

Q_OBJECT

public:

explicit chatSever(QObject *parent = 0, int port = 0);


//重载

void incomingConnection(int handle);


void sendMsgToClient(QString strMsg, int nLength);

private:

QList<tcpSocket*> m_clientSocketLst;    //用于保存客户端链表


signals:


public slots:

void updateClientsData(QString msg, int length);

void slotDisconnected(int descriptor);

};


chatSever.cpp

#include "chatsever.h"


chatSever::chatSever(QObject *parent, int port) : QTcpServer(parent)

{

//监听

listen(QHostAddress::Any, port);


}


void chatSever::incomingConnection(int handle)

{

tcpSocket* clientSocket = new tcpSocket(this);

clientSocket->setSocketDescriptor(handle);

m_clientSocketLst.append(clientSocket);


connect(clientSocket, SIGNAL(updateClientsData(QString,int)), this, SLOT(updateClientsData(QString,int)));


//一个socket断开连接就从底层链表中删除对应的对象

connect(clientSocket, SIGNAL(disconed(int)), this, SLOT(slotDisconnected(int)));

}


void chatSever::sendMsgToClient(QString strMsg, int nLength)

{

updateClientsData(strMsg, nLength);

}


void chatSever::updateClientsData(QString msg, int length)

{

for(int i = 0; i < m_clientSocketLst.count(); ++i)

{

QTcpSocket* itemClient = m_clientSocketLst.at(i);

if(itemClient->write(msg.toLatin1().data(), length) != length)

{

qDebug() << "存在数据丢失";

continue;

}

}

}


//删除指定的socket对象

void chatSever::slotDisconnected(int descriptor)

{

qDebug() << "slotDisconnected";

for(int i = 0; i < m_clientSocketLst.count(); ++i)

{

QTcpSocket* item = m_clientSocketLst.at(i);

if(item->socketDescriptor() == descriptor)

{

m_clientSocketLst.removeAt(i);

qDebug() << QString("socket列表 = : %1").arg(m_clientSocketLst.count());

return;

}

}

}


tcpSocket.h

#include <QObject>

#include <QTcpSocket>


class tcpSocket : public QTcpSocket

{

Q_OBJECT

public:

explicit tcpSocket(QObject *parent = 0);


signals:

void updateClientsData(QString, int);

void disconed(int);

public slots:

void dataRecived();

void slotDisconnected();

};



tcpSocket.cpp

#include "tcpsocket.h"


tcpSocket::tcpSocket(QObject *parent) : QTcpSocket(parent)

{

//建立处理客户端的槽函数

connect(this, SIGNAL(readyRead()), this, SLOT(dataRecived()));

connect(this, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));

}


//读取客户端信息

void tcpSocket::dataRecived()

{

while (bytesAvailable() > 0) {//貌似解决了发送方粘包的问题,加上还是好

char buf[1024] = {0};

int nLength = bytesAvailable(); //返回可用字节数

read(buf, nLength);

QString str = buf;

emit updateClientsData(str, nLength);

}

}


void tcpSocket::slotDisconnected()

{

qDebug() << "slotDisconnected";

emit disconed(socketDescriptor());

}


chatSeverUI.h

#include <QWidget>

#include <QtNetwork/QTcpSocket>

#include <QtNetwork/QTcpServer>


#include "chatsever.h"


namespace Ui {

class socketSever;

}


class chatSeverUI : public QWidget

{

Q_OBJECT


public:

explicit chatSeverUI(QWidget *parent = 0);

~chatSeverUI();


void initSocket();


public slots:

//    void acceptConnection();

//    void readClient();


private slots:

void on_pushButton_clicked();


private:

Ui::socketSever *ui;


QTcpServer* m_sever;

QTcpSocket* m_clientConet;


chatSever*  m_chatSever;

};



chatSeverUI.cpp

#include "chatseverUI.h"

#include "ui_socketsever.h"

#include <QtNetwork/qhostaddress.h>


chatSeverUI::chatSeverUI(QWidget *parent) :

QWidget(parent),

ui(new Ui::socketSever)

{

ui->setupUi(this);


m_sever = NULL;

m_clientConet = NULL;

m_chatSever = NULL;

initSocket();

}


chatSeverUI::~chatSeverUI()

{

delete ui;

}


void chatSeverUI::initSocket()

{

/*

*  方法1

m_sever = new QTcpServer(this);

m_sever->listen(QHostAddress::Any, 6666);

connect(m_sever, SIGNAL(newConnection()), this, SLOT(acceptConnection()));

*/

//方法2

m_chatSever = new chatSever(this, 6666);

if(!m_chatSever->isListening())

{

qDebug() << QString("unable to start the sever : %1").arg(m_chatSever->errorString());

}

}


/*

void chatSeverUI::acceptConnection()

{

m_clientConet = m_sever->nextPendingConnection();

connect(m_clientConet, SIGNAL(readyRead()), this, SLOT(readClient()));

}


void chatSeverUI::readClient()

{

QString str = m_clientConet->readAll();

ui->severLabel->setText(str);

}

*/

void chatSeverUI::on_pushButton_clicked()

{

QString str = ui->severEdit->text();

//m_clientConet->write(str.toLatin1().data());


m_chatSever->sendMsgToClient(str.toLatin1().data(), str.length());

}


main函数就很简单了,只是显示了各个窗口而已

chatClientUI client1;

client1.setWindowTitle("client");

client1.show();

chatClientUI client2;

client2.setWindowTitle("client");

client2.show();

chatClientUI client3;

client3.setWindowTitle("client");

client3.show();

chatSeverUI sever;

sever.setWindowTitle("sever");

sever.show();


界面是用QTDesign设计的,这里就不再多说了,初学笔记,如果有错误的地方欢迎指正,共同进步
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: