Qt浅谈之十六:TCP和UDP(之一)

原文地址::https://blog.csdn.net/taiyang1987912/article/details/36183065

相关文章

1、QT 线程池 + TCP 小试(一)线程池的简单实现----https://blog.csdn.net/goldenhawking/article/details/7854413

2、QRunnable中,如何接收tcp连接信息----https://jingyan.baidu.com/article/dca1fa6f140f54f1a440520b.html

一、简介

       Qt使用QtNetwork模块来进行网络编程,提供了一层统一的套接字抽象用于编写不同层次的网络程序,避免了应用套接字进行网络编的繁琐(因有时需引用底层操作系统的相关数据结构)。有较底层次的类如QTcpSocket、QTcpServer和QUdpSocket等来表示低层的网络概念;还有高层次的类如QNetworkRequest、QNetworkReply和QNetworkAccessManager使用相同的协议来执行网络操作;也提供了QNetworkConfiguration、QNetworkConfigurationManager和QNetworkSession等类来实现负载管理。

二、分析图

(1)网络通讯协议

(2)TCP和UDP客户端和服务器的创建流程


三、TCP

       TCP是一种可靠的、面向连接、面向数据流的传输协议,多数高层网络协议都使用TCP协议,包括HTTP和FTP,TCP协议非常适合数据的连续传输。QTcpSocket类为TCP提供了一个接口,继承自QAbstractSocket。TCP编程一般分为客户端和服务器端,即C/S(Client/Server)模型。

1、运行图

服务器监听8010端口,客户端连接。服务器端接收到连接及其信息的同时将信息发送给所有的客户端,客户端显示获得的信息。

2、代码

(1)TCP服务器端(完整代码在csdn上)

[cpp]  view plain  copy
  1. #include "tcpserver.h"  
  2. #include <QApplication>  
  3.   
  4.   
  5. int main( int argc, char **argv )  
  6. {  
  7.       
  8.     QApplication a( argc, argv );  
  9.     QTranslator translator(0);  
  10.     translator.load("tcpserver_zh",".");  
  11.     a.installTranslator(&translator);      
  12.       
  13.     TcpServer *tcpserver = new TcpServer();  
  14.     tcpserver->show();  
  15.     return a.exec();  
  16. }  
[cpp]  view plain  copy
  1. #include "tcpserver.h"  
  2.   
  3. TcpServer::TcpServer( QWidget *parent, Qt::WindowFlags  f )  
  4.     : QDialog( parent, f )  
  5. {    
  6.     QFont font("ZYSong18030",12);  
  7.     setFont(font);  
  8.           
  9.     setWindowTitle(tr("TCP Server"));  
  10.   
  11.     QVBoxLayout *vbMain = new QVBoxLayout( this );  
  12.   
  13.     ListWidgetContent = new QListWidget( this);   
  14.     vbMain->addWidget( ListWidgetContent );      
  15.   
  16.     QHBoxLayout *hb = new QHBoxLayout( );  
  17.       
  18.     LabelPort = new QLabel( this );  
  19.     LabelPort->setText(tr("Port:"));  
  20.     hb->addWidget( LabelPort );  
  21.      
  22.     LineEditPort = new QLineEdit(this);  
  23.     hb->addWidget( LineEditPort );  
  24.       
  25.     vbMain->addLayout(hb);  
  26.              
  27.     PushButtonCreate = new QPushButton( this);  
  28.     PushButtonCreate->setText( tr( "Create" ) );    
  29.     vbMain->addWidget( PushButtonCreate );  
  30.   
  31.     connect(PushButtonCreate,SIGNAL(clicked()),this,SLOT(slotCreateServer()));    
  32.   
  33.     port = 8010;   
  34.     LineEditPort->setText(QString::number(port));   
  35.   
  36. }  
  37.   
  38. TcpServer::~TcpServer()  
  39. {  
  40. }  
  41.   
  42. void TcpServer::slotCreateServer()                       
  43. {           
  44.     server = new Server(this,port);   
  45.     connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));  
  46.   
  47.     PushButtonCreate->setEnabled(false);  
  48. }  
  49.   
  50. void TcpServer::updateServer(QString msg,int length)  
  51. {  
  52.     ListWidgetContent->addItem (msg.left(length) );  
  53. }  
[cpp]  view plain  copy
  1. #include <QtNetwork>  
  2.   
  3.   
  4. #include "server.h"  
  5.   
  6. Server::Server(QObject *parent,int port)  
  7.     : QTcpServer(parent)  
  8. {  
  9.     listen(QHostAddress::Any,port);  
  10. }  
  11.   
  12. void Server::incomingConnection(int socketDescriptor)  
  13. {  
  14.     TcpClientSocket *tcpClientSocket = new TcpClientSocket(this);  
  15.     connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));  
  16.     connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int)));  
  17.       
  18.     tcpClientSocket->setSocketDescriptor(socketDescriptor);  
  19.   
  20.     tcpClientSocketList.append(tcpClientSocket);  
  21.   
  22. }  
  23.   
  24. void Server::updateClients(QString msg,int length)  
  25. {  
  26.     emit updateServer(msg,length);  
  27.   
  28.     for(int i=0;i<tcpClientSocketList.count();i++)  
  29.     {  
  30.         QTcpSocket *item=tcpClientSocketList.at(i);  
  31.         if(item->write(msg.toLatin1(), length)!=length)  
  32.         {  
  33.             continue ;  
  34.         }     
  35.     }  
  36. }  
  37.   
  38. void Server::slotDisconnected(int descriptor)  
  39. {  
  40.     for(int i=0;i<tcpClientSocketList.count();i++)  
  41.     {  
  42.         QTcpSocket *item=tcpClientSocketList.at(i);  
  43.         if(item->socketDescriptor ()==descriptor)  
  44.         {  
  45.             tcpClientSocketList.removeAt(i);  
  46.             return;  
  47.         }     
  48.     }     
  49.     return;  
  50. }  
[cpp]  view plain  copy
  1. #include "tcpserver.h"  
  2.   
  3. TcpClientSocket::TcpClientSocket( QObject *parent)  
  4. {    
  5.     connect(this, SIGNAL(readyRead()),this, SLOT(dataReceived()));     
  6.     connect(this, SIGNAL(disconnected()),this, SLOT(slotDisconnected()));  
  7. }  
  8.   
  9. TcpClientSocket::~TcpClientSocket()  
  10. {  
  11. }  
  12.                                                                                
  13. void TcpClientSocket::dataReceived()  
  14. {  
  15.     while (bytesAvailable()>0)   
  16.     {  
  17.         char buf[1024];  
  18.         int length=bytesAvailable();  
  19.         read(buf, length);  
  20.   
  21.         QString msg=buf;  
  22.           
  23.         emit updateClients(msg,length);  
  24.     }     
  25. }  
  26.   
  27. void TcpClientSocket::slotDisconnected()  
  28. {  
  29.     emit disconnected(this->socketDescriptor ());  
  30. }  
(2)TCP客户端

[cpp]  view plain  copy
  1. #include "tcpclient.h"  
  2.   
  3. TcpClient::TcpClient( QWidget *parent, Qt::WindowFlags  f )  
  4.     : QDialog( parent, f )  
  5. {    
  6.     QFont font("ZYSong18030",12, QFont::Normal);  
  7.     setFont(font);  
  8.           
  9.     setWindowTitle(tr("TCP Client"));  
  10.   
  11.     QVBoxLayout *vbMain = new QVBoxLayout( this );  
  12.       
  13.     ListWidgetContent = new QListWidget( this);   
  14.     vbMain->addWidget( ListWidgetContent );   
  15.       
  16.     QHBoxLayout *hb1 = new QHBoxLayout( );  
  17.         
  18.     LineEditSend = new QLineEdit(this);  
  19.     hb1->addWidget( LineEditSend );    
  20.   
  21.     PushButtonSend = new QPushButton( this);  
  22.     PushButtonSend->setText( tr( "Send" ) );    
  23.     hb1->addWidget( PushButtonSend );  
  24.   
  25.     vbMain->addLayout( hb1 );  
  26.   
  27.     QHBoxLayout *hb2 = new QHBoxLayout( );  
  28.   
  29.     LabelUser = new QLabel( this );  
  30.     LabelUser->setText(tr("User Name:"));  
  31.     hb2->addWidget( LabelUser );  
  32.      
  33.     LineEditUser = new QLineEdit(this);  
  34.     hb2->addWidget( LineEditUser );  
  35.   
  36.     QHBoxLayout *hb3 = new QHBoxLayout( );  
  37.   
  38.     LabelServerIP = new QLabel( this );  
  39.     LabelServerIP->setText(tr("Server:"));  
  40.     hb3->addWidget( LabelServerIP );  
  41.      
  42.     LineEditServerIP = new QLineEdit(this);  
  43.     hb3->addWidget( LineEditServerIP );  
  44.       
  45.     QHBoxLayout *hb4 = new QHBoxLayout( );  
  46.       
  47.     LabelPort = new QLabel( this );  
  48.     LabelPort->setText(tr("Port:"));  
  49.     hb4->addWidget( LabelPort );  
  50.      
  51.     LineEditPort = new QLineEdit(this);  
  52.     hb4->addWidget( LineEditPort );  
  53.       
  54.     vbMain->addLayout(hb2);  
  55.     vbMain->addLayout(hb3);  
  56.     vbMain->addLayout(hb4);  
  57.              
  58.     PushButtonEnter = new QPushButton( this);  
  59.     PushButtonEnter->setText( tr( "Enter" ) );    
  60.     vbMain->addWidget( PushButtonEnter );  
  61.   
  62.     connect(PushButtonEnter,SIGNAL(clicked()),this,SLOT(slotEnter()));  
  63.     connect(PushButtonSend,SIGNAL(clicked()),this,SLOT(slotSend()));      
  64.   
  65.     serverIP = new QHostAddress();  
  66.     port = 8010;   
  67.     LineEditPort->setText(QString::number(port));   
  68.       
  69.     status=false;  
  70.       
  71.     PushButtonSend->setEnabled( false );   
  72. }  
  73.   
  74. TcpClient::~TcpClient()  
  75. {  
  76. }  
  77.                                                                                
  78. void TcpClient::slotEnter()                       
  79. {           
  80.     if(!status)  
  81.     {  
  82.         QString ip=LineEditServerIP->text();  
  83.         if(!serverIP->setAddress(ip))  
  84.         {  
  85.             QMessageBox::information(this,tr("error"),tr("server ip address error!"));  
  86.             return;  
  87.         }  
  88.         if(LineEditUser->text()=="")  
  89.         {  
  90.             QMessageBox::information(this,tr("error"),tr("User name error!"));  
  91.             return ;  
  92.         }     
  93.         userName=LineEditUser->text();  
  94.         tcpSocket = new QTcpSocket(this);  
  95.         connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));  
  96.         connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));  
  97.         connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(dataReceived()));  
  98.           
  99.         tcpSocket->connectToHost ( *serverIP, port);  
  100.           
  101.         status=true;  
  102.     }  
  103.     else  
  104.     {  
  105.         int length = 0;   
  106.           
  107.         QString msg=userName+tr(":Leave Chat Room");  
  108.         if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())  
  109.         {  
  110.             return ;  
  111.         }             
  112.         tcpSocket->disconnectFromHost();  
  113.           
  114.         status=false;  
  115.     }  
  116.       
  117. }  
  118.   
  119. void TcpClient::slotConnected()                       
  120. {  
  121.     int length = 0;   
  122.     PushButtonSend->setEnabled( true );  
  123.     PushButtonEnter->setText(tr("Leave"));  
  124.     QString msg=userName+tr(":Enter Chat Room");  
  125.     if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())  
  126.     {  
  127.         return ;  
  128.     }     
  129. }  
  130.   
  131. void TcpClient::slotDisconnected()                       
  132. {  
  133.     PushButtonSend->setEnabled( false );  
  134.     PushButtonEnter->setText(tr("Enter"));  
  135. }  
  136.   
  137. void TcpClient::slotSend()                       
  138. {           
  139.     if(LineEditSend->text()=="")  
  140.     {  
  141.         return ;  
  142.     }  
  143.       
  144.     QString msg=userName+":"+LineEditSend->text();  
  145.       
  146.     tcpSocket->write(msg.toLatin1(),msg.length());  
  147.     LineEditSend->clear();  
  148. }  
  149.   
  150. void TcpClient::dataReceived()  
  151. {  
  152.     while (tcpSocket->bytesAvailable()>0)   
  153.     {  
  154.         QByteArray datagram;  
  155.         datagram.resize(tcpSocket->bytesAvailable());  
  156.         QHostAddress sender;  
  157.   
  158.   
  159.         tcpSocket->read(datagram.data(), datagram.size());  
  160.   
  161.         QString msg=datagram.data();  
  162.       
  163.         ListWidgetContent->addItem (msg.left(datagram.size()));  
  164.     }  
  165.   
  166. }  

3、其他TCP服务器和客户端代码

(1)TCP服务器——基本模式

[cpp]  view plain  copy
  1. #ifndef SERVER_H  
  2. #define SERVER_H  
  3.   
  4. #include <QObject>  
  5. #include <QTcpServer>  
  6.   
  7. class server : public QObject  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit server(QObject *parent = 0);  
  12.   
  13. private:  
  14.     QTcpServer *tcpServer;  
  15.     QTcpSocket *clientConnection;  
  16.   
  17. signals:  
  18.   
  19. public slots:  
  20.     void sendMessage();  
  21.     void on_Ready_Read();  
  22. };  
  23.   
  24. #endif // SERVER_H  
[cpp]  view plain  copy
  1. #include <QTcpSocket>  
  2. #include "server.h"  
  3.   
  4.   
  5. server::server(QObject *parent) :  
  6.     QObject(parent)  
  7. {  
  8.     tcpServer = new QTcpServer(this);  
  9.     // 使用了IPv4的本地主机地址,等价于QHostAddress("127.0.0.1")  
  10.     if (!tcpServer->listen(QHostAddress::Any, 59769)) {  
  11.         qDebug() << tcpServer->errorString();  
  12.     }  
  13.     connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendMessage()));  
  14. }  
  15.   
  16. void server::sendMessage()  
  17. {  
  18.     clientConnection = tcpServer->nextPendingConnection();  
  19.     clientConnection->write("hello client\r\n");  
  20.     clientConnection->flush();     
  21.     clientConnection->waitForBytesWritten(3000);  
  22.     connect(clientConnection, SIGNAL(readyRead()), this, SLOT(on_Ready_Read()));   
  23.     connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));  
  24. }  
  25. void server::on_Ready_Read()  
  26. {   
  27.     QByteArray block = clientConnection->readAll();   
  28.     qDebug() << "server = " << block;   
  29.     QString commandXml = QString("<event>" " <object>USER</object>" " <action>LOGINSUCCESS</action>" " <data>" " </data>" "</event>");   
  30.     QByteArray data = commandXml.toUtf8();   
  31.     QString str = QString("%1:%2,").arg(data.size()).arg(QString::fromUtf8(data));   
  32.     clientConnection->write(str.toUtf8()); clientConnection->disconnectFromHost();  
  33. }  
 
 

(2)TCP服务器——线程处理

[cpp]  view plain  copy
  1. #ifndef MYSERVER_H  
  2. #define MYSERVER_H  
  3.   
  4. #include <QTcpServer>  
  5. #include <QDebug>  
  6. #include "mythread.h"  
  7.   
  8. class MyServer : public QTcpServer  
  9. {  
  10.     Q_OBJECT  
  11. public:  
  12.     explicit MyServer(QObject *parent = 0);  
  13.     void StartServer();  
  14.   
  15. protected:  
  16.     void incomingConnection(int  socketDescriptor);  
  17. signals:  
  18.   
  19. public slots:  
  20.   
  21. };  
  22.   
  23. #endif // MYSERVER_H  
[cpp]  view plain  copy
  1. #ifndef MYTHREAD_H  
  2. #define MYTHREAD_H  
  3.   
  4. #include <QThread>  
  5. #include <QTcpSocket>  
  6. #include <QDebug>  
  7.   
  8. class MyThread : public QThread  
  9. {  
  10.     Q_OBJECT  
  11. public:  
  12.     explicit MyThread(int ID, QObject *parent = 0);  
  13.     void run();  
  14.   
  15. signals:  
  16.     void error(QTcpSocket::SocketError socketerror);  
  17.   
  18. public slots:  
  19.     void readyRead();  
  20.     void disconnected();  
  21.   
  22. private:  
  23.     QTcpSocket *socket;  
  24.     int socketDescriptor;  
  25.   
  26. };  
  27. #endif // MYTHREAD_H  
[cpp]  view plain  copy
  1. #include <QCoreApplication>  
  2. #include "myserver.h"  
  3.   
  4. int main(int argc, char *argv[])  
  5. {  
  6.     QCoreApplication a(argc, argv);  
  7.     MyServer server;  
  8.     server.StartServer();  
  9.   
  10.     return a.exec();  
  11. }  
[cpp]  view plain  copy
  1. #include "myserver.h"  
  2.   
  3. MyServer::MyServer(QObject *parent) :  
  4.     QTcpServer(parent)  
  5. {  
  6. }  
  7.   
  8. void MyServer::StartServer()  
  9. {  
  10.     if (!listen(QHostAddress::Any, 1234)) {  
  11.         qDebug() << "Could not start server";  
  12.     }  
  13.     else {  
  14.         qDebug() << "Listening...";  
  15.     }  
  16. }  
  17.   
  18. void MyServer::incomingConnection(int socketDescriptor)  
  19. {  
  20.     qDebug() << socketDescriptor << ":connecting...";  
  21.     MyThread *thread = new MyThread(socketDescriptor, this);  
  22.     connect(thread, SIGNAL(finished()), this, SLOT(deleteLater()));  
  23.     thread->start();  
  24. }  
[cpp]  view plain  copy
  1. #include "mythread.h"  
  2.   
  3. MyThread::MyThread(int ID, QObject *parent) :  
  4.     QThread(parent)  
  5. {  
  6.     socketDescriptor = ID;  
  7. }  
  8.   
  9.   
  10. void MyThread::run()  
  11. {  
  12.    //thread starts here  
  13.     qDebug() << socketDescriptor << ":starting thread";  
  14.     socket = new QTcpSocket;  
  15.     if (!socket->setSocketDescriptor(socketDescriptor)) {  
  16.         emit error(socket->error());  
  17.         return;  
  18.     }  
  19.     connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);  
  20.     connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);  
  21.     qDebug() << socketDescriptor << ":client connected!";  
  22.     exec();  
  23. }  
  24. void MyThread::readyRead()  
  25. {  
  26.     QByteArray Data = socket->readAll();  
  27.     qDebug() << socketDescriptor << ":Data in:" << Data;  
  28.     socket->write(Data);  
  29. }  
  30. void MyThread::disconnected()  
  31. {  
  32.     qDebug() << socketDescriptor << ":Disconnected!";  
  33.     socket->deleteLater();  
  34.     exit(0);  
  35. }  

(3)TCP服务器——线程池

[cpp]  view plain  copy
  1. #ifndef MYSERVER_H  
  2. #define MYSERVER_H  
  3.   
  4. #include <QTcpServer>  
  5. #include <QThreadPool>  
  6. #include <QDebug>  
  7. #include "myrunnable.h"  
  8.   
  9. class MyServer : public QTcpServer  
  10. {  
  11.     Q_OBJECT  
  12. public:  
  13.     explicit MyServer(QObject *parent = 0);  
  14.     void StartServer();  
  15.   
  16. protected:  
  17.     void incomingConnection(int handle);  
  18.   
  19. private:  
  20.     QThreadPool *pool;  
  21.   
  22. signals:  
  23.   
  24. public slots:  
  25.   
  26. };  
  27.   
  28. #endif // MYSERVER_H  
[cpp]  view plain  copy
  1. #ifndef MYRUNNABLE_H  
  2. #define MYRUNNABLE_H  
  3.   
  4. #include <QRunnable>  
  5. #include <QTcpSocket>  
  6. #include <QDebug>  
  7.   
  8. class MyRunnable : public QRunnable  
  9. {  
  10. public:  
  11.     MyRunnable();  
  12.     int SocketDescriptor;  
  13.   
  14. protected:  
  15.     void run();  
  16. };  
  17.   
  18. #endif // MYRUNNABLE_H  
[cpp]  view plain  copy
  1. #include "myserver.h"  
  2.   
  3. MyServer::MyServer(QObject *parent) :  
  4.     QTcpServer(parent)  
  5. {  
  6.     pool = new QThreadPool(this);  
  7.     pool->setMaxThreadCount(5);  
  8. }  
  9. void MyServer::StartServer()  
  10. {  
  11.     if (listen(QHostAddress::Any, 1234)) {  
  12.         qDebug() << "Server started!";  
  13.     }  
  14.     else {  
  15.         qDebug() << "Server did not start!";  
  16.     }  
  17. }  
  18. void MyServer::incomingConnection(int handle)  
  19. {  
  20.     MyRunnable *task = new MyRunnable();  
  21.     task->setAutoDelete(true);  
  22.     task->SocketDescriptor = handle;  
  23.     pool->start(task);  
  24. }  
[cpp]  view plain  copy
  1. #include "myrunnable.h"  
  2.   
  3. MyRunnable::MyRunnable()  
  4. {  
  5. }  
  6.   
  7. void MyRunnable::run()  
  8. {  
  9.     if (!SocketDescriptor)  return;  
  10.   
  11.     QTcpSocket socket;  
  12.     socket.setSocketDescriptor(SocketDescriptor);  
  13.   
  14.     socket.write("hello world\r\n");  
  15.     socket.flush();  
  16.     socket.waitForBytesWritten();  
  17.     socket.close();  
  18. }  
[cpp]  view plain  copy
  1. #include <QCoreApplication>  
  2. #include "myserver.h"  
  3.   
  4. int main(int argc, char *argv[])  
  5. {  
  6.     QCoreApplication a(argc, argv);  
  7.     MyServer Server;  
  8.     Server.StartServer();  
  9.     return a.exec();  
  10. }  

(4)TCP服务器——高级异步方式并使用线程池

尽可能理解这种方式,效率相对比较客观。运行结果:


[cpp]  view plain  copy
  1. #ifndef MYSERVER_H  
  2. #define MYSERVER_H  
  3.   
  4. #include <QTcpServer>  
  5. #include <QTcpSocket>  
  6. #include <QAbstractSocket>  
  7. #include "myclient.h"  
  8.   
  9. class MyServer : public QTcpServer  
  10. {  
  11.     Q_OBJECT  
  12. public:  
  13.     explicit MyServer(QObject *parent = 0);  
  14.     void StartServer();  
  15.   
  16. protected:  
  17.     void incomingConnection(int handle);  
  18.   
  19. signals:  
  20.   
  21. public slots:  
  22.   
  23. };  
  24.   
  25. #endif // MYSERVER_H  
[cpp]  view plain  copy
  1. #ifndef MYCLIENT_H  
  2. #define MYCLIENT_H  
  3.   
  4. #include <QObject>  
  5. #include <QTcpSocket>  
  6. #include <QDebug>  
  7. #include <QThreadPool>  
  8. #include "mytask.h"  
  9.   
  10. class MyClient : public QObject  
  11. {  
  12.     Q_OBJECT  
  13. public:  
  14.     explicit MyClient(QObject *parent = 0);  
  15.     void SetSocket(int Descriptor);  
  16.   
  17. signals:  
  18.   
  19. public slots:  
  20.     void connected();  
  21.     void disconnected();  
  22.     void readyRead();  
  23.     void TaskResult(int Number);  
  24.   
  25. private:  
  26.     QTcpSocket *socket;  
  27. };  
  28.   
  29. #endif // MYCLIENT_H  
[cpp]  view plain  copy
  1. #ifndef MYTASK_H  
  2. #define MYTASK_H  
  3.   
  4. #include <QRunnable>  
  5. #include <QDebug>  
  6.   
  7. class MyTask : public QObject, public QRunnable  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     MyTask();  
  12.   
  13. signals:  
  14.     void Result(int Number);  
  15.   
  16. protected:  
  17.     void run();  
  18. };  
  19.   
  20. #endif // MYTASK_H  
[cpp]  view plain  copy
  1. #include "myserver.h"  
  2.   
  3. MyServer::MyServer(QObject *parent) :  
  4.     QTcpServer(parent)  
  5. {  
  6. }  
  7. void MyServer::StartServer()  
  8. {  
  9.     if (listen(QHostAddress::Any, 1234)) {  
  10.         qDebug() << "Server started!";  
  11.     }  
  12.     else {  
  13.         qDebug() << "Server did not start!";  
  14.     }  
  15. }  
  16.   
  17. void MyServer::incomingConnection(int handle)  
  18. {  
  19.     MyClient *client = new MyClient(this);  
  20.     client->SetSocket(handle);  
  21. }  
[cpp]  view plain  copy
  1. #include "myclient.h"  
  2.   
  3. MyClient::MyClient(QObject *parent) :  
  4.     QObject(parent)  
  5. {  
  6.     QThreadPool::globalInstance()->setMaxThreadCount(15);  
  7. }  
  8.   
  9. void MyClient::SetSocket(int Descriptor)  
  10. {  
  11.     socket = new QTcpSocket(this);  
  12.   
  13.     connect(socket, SIGNAL(connected()), this, SLOT(connected()));  
  14.     connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));  
  15.     connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));  
  16.   
  17.     socket->setSocketDescriptor(Descriptor);  
  18.     qDebug() << "client connected";  
  19. }  
  20.   
  21. void MyClient::connected()  
  22. {  
  23.     qDebug() << "client connected event";  
  24. }  
  25.   
  26. void MyClient::disconnected()  
  27. {  
  28.     qDebug() << "client disconnected";  
  29. }  
  30.   
  31. void MyClient::readyRead()  
  32. {  
  33.     qDebug() << socket->readAll();  
  34.     //Time Consumer  
  35.     MyTask *mytask = new MyTask;  
  36.     mytask->setAutoDelete(true);  
  37.     connect(mytask, SIGNAL(Result(int)), this, SLOT(TaskResult(int)));  
  38.     QThreadPool::globalInstance()->start(mytask);  
  39. }  
  40.   
  41. void MyClient::TaskResult(int Number)  
  42. {  
  43.     //right here  
  44.     QByteArray Buffer;  
  45.     Buffer.append("\r\nTask Result = ");  
  46.     Buffer.append(QString::number(Number));  
  47.   
  48.     socket->write(Buffer);  
  49. }  
[cpp]  view plain  copy
  1. #include "mytask.h"  
  2.   
  3. MyTask::MyTask()  
  4. {  
  5. }  
  6.   
  7. void MyTask::run()  
  8. {  
  9.     //time consumer  
  10.     qDebug() << "Task Start";  
  11.     int iNumber = 0;  
  12.     for (int i = 0; i < 100; i++) {  
  13.         iNumber += i;  
  14.     }  
  15.     qDebug() << "Task Done";  
  16.   
  17.     emit Result(iNumber);  
  18. }  

[cpp]  view plain  copy
  1. #include <QCoreApplication>  
  2. #include "myserver.h"  
  3.   
  4. int main(int argc, char *argv[])  
  5. {  
  6.     QCoreApplication a(argc, argv);  
  7.     MyServer Server;  
  8.     Server.StartServer();  
  9.   
  10.     return a.exec();  
  11. }  

(5)TCP客户端——异步等待

[cpp]  view plain  copy
  1. #ifndef SOCKETTEST_H  
  2. #define SOCKETTEST_H  
  3.   
  4. #include <QObject>  
  5. #include <QTcpSocket>  
  6.   
  7. class SocketTest : public QObject  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     explicit SocketTest(QObject *parent = 0);  
  12.     void Connect();  
  13.   
  14. private:  
  15.     QTcpSocket *socket;  
  16.   
  17. signals:  
  18.   
  19. public slots:  
  20.   
  21. };  
  22.   
  23. #endif // SOCKETTEST_H  
[cpp]  view plain  copy
  1. #include "sockettest.h"  
  2.   
  3. SocketTest::SocketTest(QObject *parent) :  
  4.     QObject(parent)  
  5. {  
  6. }  
  7.   
  8. void SocketTest::Connect()  
  9. {  
  10.     socket = new QTcpSocket(this);  
  11.     socket->connectToHost("203.116.165.138", 80);  
  12.   
  13.     if (socket->waitForConnected(3000)) {  
  14.         qDebug() << "connected!";  
  15.   
  16.         //send  
  17.         socket->write("hello server\r\n\r\n\r\n");  
  18.         socket->waitForBytesWritten(1000);  
  19.         socket->waitForReadyRead(3000);  
  20.         qDebug() << "Reading:" << socket->bytesAvailable();  
  21.   
  22.         qDebug() << socket->readAll();  
  23.   
  24.         socket->close();  
  25.     }  
  26.     else {  
  27.         qDebug() << "not connected!";  
  28.     }  
  29. }  
(6)TCP客户端——信号槽连接
[cpp]  view plain  copy
  1. #include <QCoreApplication>  
  2. #include <QTextCodec>  
  3. #include "sockettest.h"  
  4.   
  5. int main(int argc, char *argv[])  
  6. {  
  7.     QCoreApplication a(argc, argv);  
  8.     QTextCodec *codec = QTextCodec::codecForName("System");  
  9.     QTextCodec::setCodecForLocale(codec);  
  10.     QTextCodec::setCodecForCStrings(codec);  
  11.     QTextCodec::setCodecForTr(codec);  
  12.     SocketTest mTest;  
  13.     mTest.Test();  
  14.     return a.exec();  
  15. }  
[cpp]  view plain  copy
  1. #ifndef SOCKETTEST_H  
  2. #define SOCKETTEST_H  
  3.   
  4. #include <QObject>  
  5. #include <QDebug>  
  6. #include <QTcpSocket>  
  7. #include <QAbstractSocket>  
  8.   
  9. class SocketTest : public QObject  
  10. {  
  11.     Q_OBJECT  
  12. public:  
  13.     explicit SocketTest(QObject *parent = 0);  
  14.     void Test();  
  15.   
  16. private:  
  17.     QTcpSocket *socket;  
  18.   
  19. signals:  
  20.   
  21. public slots:  
  22.     void connected();  
  23.     void disconnected();  
  24.     void bytesWritten(qint64 bytes);  
  25.     void readyRead();  
  26.     void displayError(QAbstractSocket::SocketError);  
  27. };  
  28.   
  29. #endif // SOCKETTEST_H  
[cpp]  view plain  copy
  1. #include "sockettest.h"  
  2.   
  3. SocketTest::SocketTest(QObject *parent) :  
  4.     QObject(parent)  
  5. {  
  6. }  
  7.   
  8. void SocketTest::Test()  
  9. {  
  10.     socket = new QTcpSocket(this);  
  11.     connect(socket, SIGNAL(connected()), this, SLOT(connected()));  
  12.     connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));  
  13.     connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));  
  14.     connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));  
  15.     connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));  
  16.   
  17.     qDebug() << "connecting...";  
  18.     socket->connectToHost("203.116.165.139", 80);  
  19.   
  20.     if (!socket->waitForConnected(1000)) {  
  21.         qDebug() << "Error:" << socket->errorString();  
  22.     }  
  23. }  
  24.   
  25. void SocketTest::connected()  
  26. {  
  27.     qDebug() << "connected!";  
  28.     socket->write("HEAD / HTTP/1.0\r\n\r\n\r\n");  
  29. }  
  30.   
  31. void SocketTest::disconnected()  
  32. {  
  33.     qDebug() << "disconnected!";  
  34.     socket->disconnectFromHost();  
  35. }  
  36.   
  37. void SocketTest::bytesWritten(qint64 bytes)  
  38. {  
  39.     qDebug() << "we wrote:" << bytes;  
  40. }  
  41.   
  42. void SocketTest::readyRead()  
  43. {  
  44.     qDebug() << "reading...";  
  45.     qDebug() << socket->readAll();  
  46. }  
  47. void SocketTest::displayError(QAbstractSocket::SocketError)  
  48. {  
  49.     qDebug() << socket->errorString();  
  50. }  

四、TCP总结

      以上各节代码均可单独采用实现服务器和客户端的运行,可以选择设计自己的模式。 

      TCP服务器的效率还取决于使用者设计的模式,好的设计能可以容错、快速处理大批量的任务、减小系统的负荷、节约内存等好处,因此不停的总结TCP的代码,并在其基础上提高是很有必要的。

【待续UDP】




猜你喜欢

转载自blog.csdn.net/xqhrs232/article/details/80432248