2017-09-13 6 views
1

Je dois communiquer avec un périphérique via UDP. Le problème est que QUdpSocket ne fonctionne pas du tout sans cas particulier de bind(). J'utilise la méthode connectToHost()for access to read()/write() functions.QUdpSocket ne fonctionne pas sans lier

échange UDP ne fonctionne pas du tout lorsque vous utilisez le code:

m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);  
m_udp.waitForConnected(); 

Le je ne reçois pas d'octets. Message dans Wireshark:

QUdpSocket error in Wireshark

Le code ci-dessous ne fonctionne pas trop:

m_udp.bind(QHostAddress("192.168.100.15"), 4001); 
m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);  
m_udp.waitForConnected(); 

Seul ce code fonctionne:

m_udp.bind(4001); 
m_udp.connectToHost(QHostAddress("192.168.100.15"), 4001);  
m_udp.waitForConnected(); 

Mais le code ne fonctionne que dans Qt 5.6. 2 et ne fonctionne pas dans Qt 5.4.2. Voici comment je tente de recevoir:

dev->waitForReadyRead(500); 
QByteArray ba = dev->readAll(); 

Pourquoi le comportement est si étrange? Comment peut-on comprendre cela?

Répondre

2

Vous n'avez pas montré le code de l'autre côté, mais apparemment de l'image Wireshark montré, l'homologue distant attend votre prise à être lié au port 4001.

Le premier extrait de code tente de se connecter the (RemoteAddress, 4001) sans spécifier un port local (par conséquent le noyau assigne un numéro de port arbitraire (64875 selon wireshark) mais comme mentionné ci-dessus, l'autre côté est en attendant pour renvoyer au port 4001. Donc vous ne pouvez pas recevez-le sur le port 64875.

En UDP, il n'y a pas de connexion réelle.Quand vous utilisez connectToHost vous êtes vraiment seul y spécifiant l'adresse IP et le numéro de port du côté distant. Il est de la responsabilité de l'application de s'assurer que le côté distant renvoie vers le bon port. Cela peut être fait en (a) envoyant toujours à un port particulier (comme cela est apparemment fait ici), ou (b) l'autre côté peut regarder l'adresse/le port à partir duquel le datagramme est effectivement reçu et renvoyer à celui-ci; en d'autres termes, le côté distant pouvait déterminer que le datagramme qu'il avait reçu avait été envoyé par le port 64875 et visait sa réponse à ce port. Dans la seconde tentative, vous essayez de lier votre point de terminaison local à une adresse sur l'autre machine, ce qui n'a tout simplement aucun sens. (Je devine que cet extrait fonctionnerait si vous avez modifié le lient à m_udp.bind(QHostAddress("192.168.100.3"), 4001); -. L'adresse IP de la machine locale)

Seul le troisième extrait fonctionne parce que ici vous lier au port local 4001 sans spécifier une adresse IP, puis également envoyer au port 4001 sur la machine distante. Si vous spécifiez uniquement le numéro de port dans bind, l'adresse IP sera laissée en tant que "caractère générique" et par conséquent vous devriez obtenir des paquets envoyés à ce numéro de port sur l'une des adresses IP de votre machine.

(Aucune idée pourquoi vous verrions un comportement différent dans une version antérieure de Qt.)

1

Vérifier l'état de la prise après la liaison avant même d'écrire ou de lecture.

Voir ce code:

QHostAddress serverIP("172.168.1.100"); 
if(socket->bind(serverIP,port,QUdpSocket::ShareAddress)) //even if local Host dont have static IP(on subnet expected 172.168.x.x),still it becomes true and enters if. 
    { 
    if((socket->state() == QAbstractSocket::BoundState) && (((socket->localAddress()).protocol()) == QAbstractSocket::IPv4Protocol)) //ignore protocol validation if not required. 
     { 

     } 
else 
     { 
      qDebug()<<"Socket not in bound state. address is: "<<QHostAddress::LocalHost<<" and the port "<<port; 
      //Return = false; 
     } 
    } 
else 
    { 
     qDebug()<<"Failed to bind socket to the address "<<QHostAddress::LocalHost<<" and the port "<<port; 
     //Return = false; 
    } 

En second lieu, prises dans Qt émettra des signaux d'erreur si quelque chose va mal. Donc, vous devriez avoir une fente pour attraper ces signaux d'erreur. De cette façon, vous pouvez connaître la raison derrière le problème.

pour l'exemple:

connect(udpsocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(onSocketError(QAbstractSocket::SocketError))); 

fente pour recevoir les erreurs de socker:

void SomeInterface::onSocketError(QAbstractSocket::SocketError socketError) 
{ 
    qDebug()<<"socket error occured and the error is : "<<socketError; 
}