2017-07-06 1 views
0

J'apprends la programmation Android et Java par moi-même. Pour la pratique, j'ai développé quelques applications, et maintenant j'essaye d'écrire une application de chat. Donc, fondamentalement, je veux quelque chose comme WhatsApp. J'ai un programme de serveur également codé par moi fonctionnant dans mon ordinateur, et c'est ce que la conversation dans le système d'Android utilise pour communiquer. Donc, fondamentalement, tout est envoyé au serveur et le serveur fait ce qu'il faut pour livrer les messages.

Voici donc ce que j'ai:Sockets Android: l'écoute ne fonctionne pas à travers 4G

  1. D'abord, mon application envoie un « Bonjour » à mon serveur (IP connu et le port)
  2. Le serveur stocke l'adresse IP et le port (également le nom d'utilisateur) utilisé par chaque utilisateur
  3. Lorsque le serveur est invité à transmettre un message à un utilisateur, il l'envoie à l'adresse IP et le port stocké

J'utilise une prise pour le « Bonjour », mais je ne peux pas utiliser le même pour renvoyer des messages (à cause de comment j'ai programmé le serveur). Mais ce n'est pas le problème. Lorsque le serveur reçoit le "Hello", il écoute sur le port correspondant. Mais quand le serveur est celui qui doit démarrer la connexion, c'est l'application qui doit le faire. Pour ce faire, l'application doit savoir sur quel port elle doit écouter (elle ne sait pas à cause de NAT), et je lui dis donc de renvoyer le port utilisé via le premier socket utilisé pour le message "Hello". Malgré cela, mon application est incapable de recevoir des messages et reste dans l'appel de réception.

Ici vous avez le code:

Serveur:

DatagramSocket client = new DatagramSocket(2048); //Predefined port 
    DatagramPacket receivePacket; 
    byte[] receiveData = new byte[1024]; 
    receivePacket = new DatagramPacket(receiveData, 
      receiveData.length); 
    System.out.println("Ready to receive"); 
    client.receive(receivePacket); 
    System.out.println("Received successfuly"); 
    String receivedPort = String.valueOf(receivePacket.getPort()); 
    byte[] sendData = receivedPort.getBytes(); 
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, receivePacket.getAddress(), receivePacket.getPort()); 
    client.send(sendPacket); //Send back the port used by the app 
    System.out.println("Sent successfuly"); 
    client.close(); 
    Thread.sleep(1000); //To make sure the app is ready to listen 
    DatagramSocket socket = new DatagramSocket(); 
    byte[] sendData2 = "Working like a charm".getBytes(); 
    InetAddress ip = receivePacket.getAddress(); 
    int port = receivePacket.getPort(); 
    System.out.println(ip + " " + port); 
    DatagramPacket sendPacket2 = new DatagramPacket(sendData2, sendData2.length, ip, port); 
    socket.send(sendPacket); 
    System.out.println("Sent successfuly 2nd time"); 
    socket.close(); 

client (application Android):

EditText eT = (EditText) findViewById(R.id.messageText); 
String message = eT.getText().toString(); 
DatagramSocket socket = new DatagramSocket(); 
byte[] sendData = message.getBytes(); 
InetAddress ip = InetAddress.getByName(MY_COMPUTER'S_IP); 
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, 2048); 
socket.send(sendPacket); 
byte[] receiveData = new byte[1024]; 
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 
socket.receive(receivePacket); //Receive the port used (and that must be opened and redirecting the traffic to this device due to NAT) 
socket.close(); 
String receivedMessage = new String(receivePacket.getData()); 
String receivedData = new String(receivePacket.getData()); 
String actualData = receivedData.substring(0, receivePacket.getLength()); 
Log.d("Port", actualData); 
int port = Integer.parseInt(actualData); 
DatagramSocket socket2 = new DatagramSocket(port); 
DatagramPacket receivePacket2; 
byte[] receiveData2 = new byte[1024]; 
receivePacket2 = new DatagramPacket(receiveData2, 
     receiveData2.length); 
socket2.receive(receivePacket2); //Here is where it gets blocked 
String data = new String(receivePacket2.getData()); 
Log.d("Finally received", data.substring(receivePacket2.getLength())); 
socket2.close(); 
Quelqu'un sait-il pourquoi mes messages ne font pas en arrière à travers la deuxième prise? J'ai vérifié et l'IP et les ports sont corrects.

Merci d'avance pour votre réponse, et je m'excuse pour mon formatage.
+0

Peut-être qu'un pare-feu bloque la communication – Luftbaum

Répondre

0

De nombreuses sociétés de téléphonie mobile attribuent actuellement une adresse IP privée aux appareils connectés 3G-4G.

C'est comme si les périphériques étaient à l'intérieur d'un réseau local. Vous n'avez pas accès au routeur passerelle de ce réseau local et sans NAT, les ports d'écoute de votre appareil sont inaccessibles de l'extérieur. Pour savoir si votre adresse IP est publique ou privée, comparez l'adresse IP de l'appareil avec les sites tels que showmyip.com, s'ils sont différents, votre appareil se trouve dans votre compagnie de téléphone LAN.

Pour obtenir l'IP du périphérique, certaines applications comme PingTools peuvent vous aider.

+0

Oui, l'adresse IP de mon appareil est privée. Ce que je fais est d'écouter sur le port assigné par la tour (qui agit comme un routeur), donc si un datagramme est envoyé à l'IP de la tour (le public de mon périphérique) et sur le port d'où il vient, il devrait à mon appareil, non? La tour voit quelqu'un répondre à ce périphérique car il sait que le port correspond à ce périphérique. Sauf si l'appel close() ferme le port ... – ErikMB

+0

Non, comme je l'ai dit, vos ports d'écoute sont inaccessibles de l'extérieur. Même chose si vous vous connectez via Wi.FI et que vous ne créez pas de règle NAT dans le routeur. –

+0

Et cette hypothèse que le routeur de l'entreprise redirige les paquets vers votre port est 100% faux. Cet automatisme magique n'existe pas. La seule façon dont l'appareil avec une adresse IP privée 4G peut se connecter au monde extérieur est de se connecter via TCP à un serveur externe, puis si une connexion est établie, le serveur externe peut envoyer des paquets à votre appareil Android. –

0

D'abord, dites-moi, est le périphérique connecté à l'adresse IP directe ou le sous-réseau? L'appareil possède-t-il une adresse IP comme l'adresse IP locale 192.168 ..? et est le NAT configuré correctement sur le routeur pour transférer les paquets vers le port respectif sur le périphérique?

Ce que je soupçonne que vous pouvez envoyer un périphérique parce que le serveur IP va être statique. En le recevant pourrait ne pas atteindre l'appareil ... Vous me dites quelle est l'adresse IP de l'appareil et le serveur ..

Une fois après ypu a répondu, nous pouvons comprendre le problème. Dans android, c'est mieux si vous utilisez les websockets et envoyer et recevoir les messages sur une connexion wss. Pour réduire la consommation d'énergie, essayez d'utiliser le service de notification push google ou le service de messagerie Firebase pour activer la fonctionnalité de chat.

+0

Tout d'abord, merci d'avoir répondu. Alors oui, l'adresse IP de mon serveur est statique, comme il se doit. L'appareil n'est pas, j'essaye de le faire en 4G. Donc, je sais que lorsqu'un datagramme est envoyé, l'antenne agit comme un routeur et ajoute le port à la liste des ports, donc si quelque chose est reçu à ce port, il est redirigé vers l'appareil. Je suppose que si je sais quel était ce port (que l'antenne a choisi) et que j'écoute dessus, je peux recevoir des messages envoyés à mon adresse IP publique (qui est l'adresse IP de l'antenne) et le port spécifié. Est-ce correct? – ErikMB

+0

Pourquoi ne pas essayer de créer une connexion socket avec le serveur du client sur le port particulier plutôt que le périphérique créant le port dynamique ..? Donc, vous pouvez être assez sûr du droit du port .. – PranavKAndro

+0

C'est ce que je fais si je vous comprends correctement. – ErikMB