当前位置:   article > 正文

QTcpServer 服务端处理多个客户端2-InComingConnection方式_incomingconnection函数详解

incomingconnection函数详解

目录

一、QTcpServer

二、QTcpSocket

三、incomingConnection

四、QTcpServer 服务端处理多个客户端

1、客户端

2、服务器

(1)、服务器server

(2)、服务器线程

(3)、服务器socket


一、QTcpServer


     QTcpServer用于接收到来的TCP连接。端口号即可指定,也可由QTcpServer自动选取一个。既可在设备上指定的IP地址上监听,也可在设备上所有IP地址上监听。调用Listen()让服务端监听到来的连接。当一个客户端连接到服务端时,一个newConnection()信号随后发出。调用nextPendingConnection()去接收等待的QTcpSocket连接。函数返回一个QAbstractSocket::ConnectedState状态的QTcpSocket对象指针,用于与客户端通信。若发生错误,serverError()返回错误类型,errorString()返回一条关于错误如何发生的常人可读描述。监听连接时,serverAddress()和serverPort()分别用于获取处于监听状态服务端的ip地址和端口。close()使QTcpServer停止继续监听到来的连接。虽然QTcpServer被设计成使用事件循环,但也有一种不用事件循环的例外。那种情况下,必须使用waitForNewConnection()。waitForNewConnection()将一直阻塞,直到有一个连接使可获取的或发生超时。

The QTcpServer class provides a TCP-based server.

This class makes it possible to accept incoming TCP connections. You can specify the port or have QTcpServer pick one automatically. You can listen on a specific address or on all the machine's addresses.

Call listen() to have the server listen for incoming connections. The newConnection() signal is then emitted each time a client connects to the server.

Call nextPendingConnection() to accept the pending connection as a connected QTcpSocket. The function returns a pointer to a QTcpSocket in QAbstractSocket::ConnectedState that you can use for communicating with the client.

If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human readable description of what happened.

When listening for connections, the address and port on which the server is listening are available as serverAddress() and serverPort().

Calling close() makes QTcpServer stop listening for incoming connections.

Although QTcpServer is mostly designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForNewConnection(), which blocks until either a connection is available or a timeout expires.

Symbian Platform Security Requirements

On Symbian, processes which use this class must have the NetworkServices platform security capability. If the client process lacks this capability, it will lead to a panic.

Platform security capabilities are added via the TARGET.CAPABILITY qmake variable.

二、QTcpSocket


     QTcpSocket 类提供一个TCP套接字。TCP是一个面向连接,可靠的的通信协议,非常适合于连续不断的数据传递。QTcpSocket 是QAbstractSocket类非常方便的一个子类,让你创建一个TCP连接和数据流交流。

The QTcpSocket class provides a TCP socket.

TCP (Transmission Control Protocol) is a reliable, stream-oriented, connection-oriented transport protocol. It is especially well suited for continuous transmission of data.

QTcpSocket is a convenience subclass of QAbstractSocket that allows you to establish a TCP connection and transfer streams of data. See the QAbstractSocket documentation for details.

Note: TCP sockets cannot be opened in QIODevice::Unbuffered mode.

Symbian Platform Security Requirements

On Symbian, processes which use this class must have the NetworkServices platform security capability. If the client process lacks this capability, it will result in a panic.

Platform security capabilities are added via the TARGET.CAPABILITY qmake variable.

三、incomingConnection

        This virtual function is called by QTcpServer when a new connection is available. The socketDescriptor argument is the native socket descriptor for the accepted connection.

        The base implementation creates a QTcpSocket, sets the socket descriptor and then stores the QTcpSocket 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.

        If this server is using QNetworkProxy then the socketDescriptor may not be usable with native socket functions, and should only be used with QTcpSocket::setSocketDescriptor().

        Note: If you want to handle an incoming connection as a new QTcpSocket object in another thread you have to pass the socketDescriptor to the other thread and create the QTcpSocket object there and use its setSocketDescriptor() method.

四、QTcpServer 服务端处理多个客户端

1、客户端

        客户端的主要功能包括:连接服务器,断开服务器,向服务器发送数据。

  1. class MySocket : public QTcpSocket
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ClientSocket(QObject *parent = Q_NULLPTR);
  6. ~ClientSocket();
  7. bool Connect(QHostAddress hadd,ushort port);//连接服务器
  8. void disConnect();//断开服务器
  9. void transMess(const QString &str);//向服务器发送数据
  10. signals:
  11. void dataReady(const QString &ip, const QByteArray &data);//从服务器接收到数据后向界面层发送信号
  12. private slots:
  13. void recvData();//对QTcpSocket 接收到数据产生的信号设定的槽函数
  14. };
  15. //.cpp
  16. MySocket::MySocket(QObject *parent) :QTcpSocket(parent)
  17. {
  18. connect(this,SIGNAL(readyRead()),this,SLOT(recvData()));
  19. }
  20. MySocket::~MySocket()
  21. {
  22. }
  23. bool MySocket::connect(QHostAddress hadd,ushort port)
  24. {
  25. this->connectToHost(hadd,port);
  26. if (this->waitForConnected(1000)) // 连接成功则true
  27. {
  28. return true;
  29. }
  30. return false;
  31. }
  32. void MySocket::disConect()
  33. {
  34. this->disconnectFromHost();//断开连接
  35. }
  36. void MySocket:: transMess(const QString &str)//发送数据
  37. {
  38. this->write(str.toLocal8Bit());
  39. }
  40. void MySocket:: recvData() //从服务器接收到数据后
  41. {
  42. QString ip = peerAddress().toString().remove(0, 7);
  43. QByteArray data = readAll();
  44. emit dataReady(ip, data); //向界面层发送带数据的信号量
  45. }

2、服务器

(1)、服务器server

  1. class Server : public QTcpServer
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit Server(QObject *parent = Q_NULLPTR);
  6. ~Server();
  7. private:
  8. void incomingConnection(int sockDesc); //QTcpServer中被重写的函数,该函数在客户端接入时被调用
  9. private slots:
  10. void clientDisconnected(int sockDesc); //当产生客户端断开连接时向上层发送信号
  11. private:
  12. QList<int> m_socketList; //服务器Socket ID链表
  13. };
  14. //.cpp
  15. //这里的Server类继承于QTcpServer,
  16. //重写其中的void incomingConnection(int sockDesc)方法,
  17. //该方法在有客户端接入时自动调用。
  18. //每当一个新的客户端连接时,通过标识码socketDescriptor,实现与对应的客户端通信
  19. void Server::incomingConnection(int sockDesc)
  20. {
  21. m_socketList.append(sockDesc);//客户端ID 加入链表
  22. ServThread *thread = new ServThread(sockDesc); //创建服务器处理进程
  23. thread->start();
  24. }

(2)、服务器线程

  1. class ServThread : public QThread
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ServThread(int sockDesc, QObject *parent = Q_NULLPTR);
  6. ~ServThread();
  7. private:
  8. void run(void);
  9. signals:
  10. void disconnectTCP(int sockDesc);
  11. private slots:
  12. void disconnectToHost(int);
  13. private:
  14. ServSocket *m_socket;
  15. int m_sockDesc;
  16. };
  17. void ServThread:: disconnectToHost(int)
  18. {
  19. emit disconnectTCP(m_sockDesc);
  20. m_socket->disconnectFromHost();//断开连接
  21. this->quit();
  22. }
  23. void ServThread::run(void)
  24. {
  25. m_socket = new ServSocket(m_sockDesc);//需要在线程中创建,这样才能实现多线程处理
  26. if (!m_socket->setSocketDescriptor(m_sockDesc)) {
  27. //设置discripter这句必须得有,否则socket中接受不到数据
  28. return ;
  29. }
  30. connect(m_socket,SIGNAL(sig_disconnect(int)),this,SLOT(disconnectToHost(int)));
  31. this->exec();//在Qt中启动消息机制
  32. }

(3)、服务器socket

  1. class ServSocket: public QTcpSocket
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ServSocket(int sockDesc, QObject *parent = Q_NULLPTR);
  6. ~ServSocket();
  7. public slots:
  8. void recvData(void);
  9. void sendData(int id, const QByteArray &data);
  10. void slot_disconnect();
  11. private:
  12. int m_sockDesc;
  13. };
  14. //.c
  15. ServSocket::ServSocket(int sockDesc,QObject *parent) :QTcpSocket(parent)
  16. {
  17. m_sockDesc = sockDesc;
  18. connect(this,SIGNAL(disconnected),this,SLOT(slot_disconnect));
  19. connect(this,SIGNAL(readyRead()),this,SLOT(recvData()));//底层信号readyRead -> recvDate
  20. }
  21. ServSocket::~ServSocket()
  22. {
  23. }
  24. void ServSocket::slot_disconnect()
  25. {
  26. emit sig_disconnect(m_sockDesc);
  27. }
  28. void ServSocket:: recvData()
  29. {
  30. QByteArray data = readAll();
  31. //进行处理
  32. }
  33. void ServSocket:: sendData(int id, const QByteArray &data)
  34. {
  35. if (id == m_sockDesc && !data.isEmpty()) {
  36. this->write(data);
  37. }
  38. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/930632
推荐阅读
相关标签
  

闽ICP备14008679号