赞
踩
因为项目中要用到TCP客户端的并发处理,所以TCP服务端用多线程去实现是必要的。于是花了一大早上的时间写了一各Demo
如图:
主要关键代码:
#include "tcpserverthread.h" serverThread::serverThread(int sockDesc, QObject *parent) : QThread(parent), m_sockDesc(sockDesc) { connect(this, SIGNAL(clientconnected(QString)), this, SLOT(connectToHost(QString))); // connect(m_tcpsocket, SIGNAL(sigDisconnectAll()), this, SLOT(disconnectAll())); } serverThread::~serverThread() { m_socket->close(); } void serverThread::run(void) { m_socket = new MySocket(m_sockDesc); if (!m_socket->setSocketDescriptor(m_sockDesc)) { return ; } QString ip = m_socket->peerAddress().toString(); int port = m_socket->peerPort(); strIP = QString("%1:%2").arg(ip).arg(QString ::number(port)); emit testsignal(strIP); emit clientconnected(strIP); //断开 connect(m_socket, &MySocket::disconnected, this, &serverThread::disconnectToHost); //接收 connect(m_socket, SIGNAL(dataReady(const QString&, const QByteArray&)), this, SLOT(recvDataSlot(const QString&, const QByteArray&))); //发送 connect(this, SIGNAL(sendData(int, QString,const QByteArray&)), m_socket, SLOT(sendData(int,QString, const QByteArray&))); // connect(m_socket, SIGNAL(aboutToClose()), thread, SLOT(deleteLater())); this->exec(); } //mainwindows 窗口会发送socket发送信号,接收信号并处理 void serverThread::sendDataSlot(int sockDesc, QString str, const QByteArray &data) { if (data.isEmpty()) { return ; } emit sendData(sockDesc, str,data); } void serverThread::recvDataSlot(const QString &ip, const QByteArray &data) { emit dataReady(ip, data); } void serverThread::disconnectToHost(void) { emit disconnectTCP(m_sockDesc,strIP); m_socket->disconnectFromHost(); this->quit(); } void serverThread::connectToHost(QString str) { emit connectTCP(m_sockDesc,str); }
2、tcpServer端对接入客户端需要重写 函数incomingConnection()
This virtual function is called by QLocalServer when a new connection is available. socketDescriptor is the native socket descriptor for the accepted connection.
The base implementation creates a QLocalSocket, sets the socket descriptor and then stores the QLocalSocket in an internal list of pending connections. Finally newConnection() is emitted.
Reimplement this function to alter the server’s behavior when a connection is available.
void MyTcpServer::incomingConnection(int sockDesc) { m_socketList.append(sockDesc); serverThread *thread = new serverThread(sockDesc); //显示连接数 connect(thread, SIGNAL(connectTCP(int,QString )), m_Widget, SLOT(showConCont(int,QString))); //显示客户端IP connect(thread, SIGNAL(connectTCP(int,QString )), m_Widget, SLOT(showConnection(int,QString))); connect(thread, SIGNAL(disconnectTCP(int,QString)), m_Widget, SLOT(showDisconnection(int,QString))); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); //接收数据 connect(thread, SIGNAL(dataReady(const QString&, const QByteArray&)), m_Widget, SLOT(recvData(const QString&, const QByteArray&))); //发送数据 connect(m_Widget, SIGNAL(sendData(int,QString, const QByteArray&)), thread, SLOT(sendDataSlot(int,QString, const QByteArray&))); thread->start(); }
3、为了增加代码的可读性,这里新建一个类mysocket 来单独收发数据
//发送数据 void MySocket::sendData(int id, QString str,const QByteArray &data) { QString ip = peerAddress().toString(); int port = peerPort(); ip = QString("%1:%2").arg(ip).arg(QString ::number(port)); if(str == ip) { if (!data.isEmpty()) { this->write(data); } } } void MySocket::recvData(void) { QString ip = peerAddress().toString(); int port = peerPort(); ip = QString("%1:%2").arg(ip).arg(QString ::number(port)); QByteArray data = readAll(); emit dataReady(ip, data); }
本示例下载地址:https://download.csdn.net/download/qq_21291397/12364249
总结:
TCP 服务端的创建不难,重点还是要理解多线程的那层含义。实操动手写一写代码,可以提高对多线程的理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。