QTcpSocket false 连接到 QTcpServer

Posted

技术标签:

【中文标题】QTcpSocket false 连接到 QTcpServer【英文标题】:QTcpSocket false connect to QTcpServer 【发布时间】:2012-12-18 18:33:48 【问题描述】:

自从一段时间以来我一直在使用 Qt(对不起我的英语)。我现在正在使用 QtNetwork。

我需要创建一个类似系统的客户端-服务器。基本思路如下:

(客户端和服务器)的 IP 可以更改。无法将服务器 IP 存储在客户端的配置文件中。因此,服务器必须以某种方式公开其 IP,并且客户端必须能够检测到要连接的服务器 IP。

客户端必须能够在没有服务器的情况下工作,并更新服务器(一旦连接)它的工作。

客户端和服务器运行在同一个WLAN网络中,因此无需通过互联网连接。

这个新系统旨在替换旧系统(也包括客户端和服务器)。旧服务器仅使用 UDP 广播消息与客户端通信,因此有时消息会丢失。

所以,对于第一点,我在服务器中实现了一个计时器。此计时器每 X 次通过 UDP 发送一条带有消息“连接到服务器”的广播消息。此消息的想法是客户端检测到此类消息并获取服务器 IP 进行连接。

服务器使用 QTcpServer 检测客户端连接,并为每个客户端存储一个新的 QTcpSocket 进行通信。

客户端在获得服务器 IP 后使用 TcpSocket 进行连接。

听起来很简单。

我已经实现了连接系统,并且,在本地机器上(服务器和一些客户端在同一台机器上运行),系统可以正常工作。可以完成连接并且可以进行通信。客户端和服务器都使用 gcc 4.7.2 在 Chakra Linux 64 位上编译。系统安装的Qt版本是4.8.4。

现在,我用两台真机测试了系统(服务器在 Chakra Linux 64 位上运行,客户端在 Windows 7(一些 32 位和另一个 64 位)和两台 Windows 8(只有 32 位)上运行)。客户端的 Windows 版本已在运行 Windows 7 32 位、Qt 4.8.3 和 MingW 4.6.2 的虚拟机 (VirtualBox 4.2.4) 上编译。 Windows 客户端运行所有 32 位编译版本的客户端(所有 32 位 Windows 机器和 64 位 Windows 机器)。

客户端可以检测和读取广播消息(UDP,工作在45454端口),一旦他们得到服务器IP(检测到的IP是正确的),他们会尝试连接。

问题是,从 7 个客户端中,只有一个 Windows 8 连接了一次。所有客户端都尝试连接,所有的QTcpSocket都发出“已连接”信号,但服务器没有检测到任何连接。

这完全是随机的,因为有时我可以连接 1 或 2 个客户端。其他时候没有。

此代码用于客户端广播初始化。

broadcast_socket = new QUdpSocket ();
server_connection = new QTcpSocket ();
if ( broadcast_socket->bind ( QHostAddress::Any , cfg->networkControl ()->udpPort () ) == false )

   cout << ">> NetworkManager: Error setting port " << cfg->networkControl ()->udpPort () << " for UDP broadcast listen." << endl;

connect ( broadcast_socket , SIGNAL ( readyRead () ) , this , SLOT ( broadcastMessageReceived () ) );
connect ( server_connection , SIGNAL ( readyRead () ) , this , SLOT ( serverMessageReceived () ) );
connect ( server_connection , SIGNAL ( disconnected () ) , this , SLOT ( serverConnectionLost () ) );
connect ( server_connection , SIGNAL ( connected () ) , this , SLOT ( serverConnected () ) );

此代码来自客户端,当接收到服务器广播消息时。

void NetworkManager::broadcastMessageReceived ( void )

   while ( broadcast_socket->hasPendingDatagrams () )
   
      QByteArray datagram;
      QHostAddress sender_adress;
      datagram.resize ( broadcast_socket->pendingDatagramSize () );
      broadcast_socket->readDatagram ( datagram.data () , datagram.size () , &sender_adress );
      server_ip = sender_adress;

      QString message ( datagram.data () );

      cout << ">> NetworkManager: Broadcast message received: " << message.toStdString () << endl;      
      if ( message == QString ( "0:%1" ).arg ( NetworkMessages::ConnectToServer ) )
               
         if ( connection_status == 0 ) // If 0, there is no connection still.
         
            cout << endl << "   Server asking for connection." << endl;
            cout << "   Server IP: " << sender_adress.toString ().toStdString () << endl;
            cout << "   Trying to connect." << endl;
            server_connection->connectToHost ( sender_adress , cfg->networkControl ()->tcpPort () );        
            cout << "   Waiting for responce." << endl;        
            connection_status = 1;
            break;
         
      
    
   return;

在服务器端,我有这段代码要初始化:

connection_server = new QTcpServer ();
connect ( connection_server , SIGNAL ( newConnection () ) , this , SLOT ( connectClient () ) );

if ( connection_server->listen ( QHostAddress::Any , cfg->networkControl ()->tcpPort () ) == false )

   cout << ">> NetworkManager: Error setting port " << cfg->networkControl ()->tcpPort () << " for TCP server use" << endl;

这是连接新客户端的部分代码:

void NetworkManager::connectClient ( void )

   cout << ">> NetworkManager: New client request." << endl;
   QTcpSocket* new_client = connection_server->nextPendingConnection ();
   connection_sockets[ i ] = new_client; // This is a QList of QTcpSocket pointers, the value of 'i' is calculated previously
   connect ( new_client , SIGNAL ( readyRead () ) , connection_listeners[ i ] , SLOT ( readyRead () ) );
   connect ( new_client , SIGNAL ( disconnected () ) , connection_listeners[ i ] , SLOT ( disconnected () ) );
   connection_state[ i ] = 1;

   cout << "   Asking to client with IP " << new_client->peerAddress ().toString ().toStdString () << " identify." << endl;
   connection_state[ i ] = 1;

   sendToClient ( QObject::tr ( "0:%1" ).arg ( NetworkMessages::IdentifyYourself ) , i );

“sendToClient”成员函数只在连接后向客户端发送消息。

所以,问题是,我不知道为什么会有如此随机的连接,大部分时间是错误连接(客户端再次发出连接信号,但在服务器端没有发出任何信号当客户端连接时...)。

我不知道我做错了什么......

客户端和服务器都使用 UDP 端口 45454 和 TCP 端口 8888。我已经更改了 TCP 端口值(在客户端、服务器和两者上)和同样的故事。我更改了 TCP 端口,如果两者上的端口不同,则消息不会到达客户端...

对不起,长文,但我认为最好告诉你我做了什么......

我正在寻找关于哪一个可能是我的问题的建议,或者如果我的代码有问题...但请记住,有时(并且只是有时)一两个客户端可以真正连接...

【问题讨论】:

【参考方案1】:

connection_status = 1;

void NetworkManager::broadcastMessageReceived ( void ) 中不应存在。当连接成功时,应该在serverConnected () 中设置。

【讨论】:

值 connection_status 是一个整数值,用于客户端跟踪连接过程(0=未连接,1=等待服务器响应,2=等待密码验证,3=连接的)。我在发帖时忘记删除代码中的这一行。我希望我的错误更正可以帮助你帮助我n_n

以上是关于QTcpSocket false 连接到 QTcpServer的主要内容,如果未能解决你的问题,请参考以下文章

QTcpSocket重连方式

无法写入 QRunnable 内的 QTcpSocket

QDataStream 和 QTcpSocket 上的发送和接收结构

QTcpSocket 不发出错误信号

Qt:设计QtcpSocket连接多个TcpServer?

QTcpSocket 客户端自动重连