2017-08-31 1 views
1

Je suis nouveau à la programmation avec Message Queues en général et j'ai essayé de travailler sur une application Android simple qui utilise ZeroMQ. Je cours le programme de serveur et de client sur le même périphérique dans des threads distincts. Ceci est ma Server classe:L'application se ferme quand socket.bind() est appelée - JeroMQ sur Android

public class ZeroMQServer implements Runnable{ 
private Handler uiThreadHandler; 

public ZeroMQServer(Handler uiThreadHandler) { 
    this.uiThreadHandler = uiThreadHandler; 
} 

@Override 
public void run() { 
    ZMQ.Context context = ZMQ.context(1); 
    ZMQ.Socket socket = context.socket(ZMQ.REP); 
    socket.bind("tcp://*:5570"); 

    while(!Thread.currentThread().isInterrupted()) { 
     byte[] msg = socket.recv(0); 
     uiThreadHandler.sendMessage(
       Util.bundledMessage(uiThreadHandler, new String(msg))); 
     socket.send(Util.reverseInPlace(msg)+"", 0); 
    } 
    socket.close(); 
    context.term(); 
} 

Et c'est la classe client:

public class ZeroMQMessageTask extends AsyncTask<String, Void, String> { 
private final Handler uiThreadHandler; 

public ZeroMQMessageTask(Handler uiThreadHandler){ 
    this.uiThreadHandler = uiThreadHandler; 
} 

@Override 
protected String doInBackground(String... params) { 
    ZMQ.Context context = ZMQ.context(1); 
    ZMQ.Socket socket = context.socket(ZMQ.REQ); 
    socket.connect("tcp://localhost:5570"); 

    socket.send(params[0].getBytes(), 0); 
    String result = new String(socket.recv(0)); 

    socket.close(); 
    context.term(); 

    return result; 
} 

@Override 
protected void onPostExecute(String result) { 
    uiThreadHandler.sendMessage(Util.bundledMessage(uiThreadHandler, result)); 
} 

Et voici l'extrait de l'activité principale qui démarre le serveur dans un autre thread et met en œuvre un clickListener pour appeler le client.

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    textView = (TextView)findViewById(R.id.text_console); 
    editText = (EditText)findViewById(R.id.text_message); 

    new Thread(new ZeroMQServer(serverMessageHandler)).run(); 

    findViewById(R.id.button_send_message).setOnClickListener(
      new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        new ZeroMQMessageTask(clientMessageHandler).execute(getTaskInput()); 
       } 

       protected String getTaskInput() { 
        return editText.getText().toString(); 
       } 
      }); 
} 

Le problème que j'ai est que dès que l'application démarre, elle se ferme automatiquement. Lorsque je supprime la ligne socket.bind("tcp://*:5570"); du serveur, elle ne se ferme plus, mais ne fonctionne pas comme prévu, car le serveur n'écoute pas.

J'ai les deux autorisations INTERNET et ACCESS_WIFI_STATE accordées dans le manifeste.

Toute aide à ce sujet est appréciée.

EDIT: J'ai mis un point d'arrêt à la .bind() ligne, ce qui est l'erreur que je reçois:

Didn't find class "java.net.StandardProtocolFamily" on path: 
    DexPathList[ 
    [zip file "/data/app/com.example.victor.zeromqrabbitmq-1/base.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_dependencies_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_0_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_1_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_2_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_3_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_4_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_5_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_6_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_7_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_8_apk.apk", 
    zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_9_apk.apk" 
    ], 
    nativeLibraryDirectories=[ 
    /data/app/com.example.victor.zeromqrabbitmq-1/lib/arm, 
    /vendor/lib, /system/lib 
    ] 
    ] 

EDIT2: erreur logcat complète:

09-01 00:44:19.878 13082-13205/com.example.victor.zeromqrabbitmq E/Error: Exception: 
09-01 00:44:20.188 13082-13205/com.example.victor.zeromqrabbitmq E/AndroidRuntime: FATAL EXCEPTION: 
     AsyncTask #1 
     Process: com.example.victor.zeromqrabbitmq, PID: 13082 
     java.lang.RuntimeException: An error occurred while executing doInBackground() 
      at android.os.AsyncTask$3.done(AsyncTask.java:309) 
      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) 
      at java.util.concurrent.FutureTask.setException(FutureTask.java:223) 
      at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
      at java.lang.Thread.run(Thread.java:818) 
     Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/net/StandardProtocolFamily; 
      at zmq.io.net.tcp.TcpAddress.family(TcpAddress.java:50) 
      at zmq.io.net.tcp.TcpListener.setAddress(TcpListener.java:171) 
      at zmq.SocketBase.bind(SocketBase.java:363) 
      at org.zeromq.ZMQ$Socket.bind(ZMQ.java:2333) 
      at com.example.victor.zeromqrabbitmq.ZeroMQServer.doInBackground(ZeroMQServer.java:24) 
      at com.example.victor.zeromqrabbitmq.ZeroMQServer.doInBackground(ZeroMQServer.java:10) 
      at android.os.AsyncTask$2.call(AsyncTask.java:295) 
      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
      at java.lang.Thread.run(Thread.java:818) 
     Caused by: java.lang.ClassNotFoundException: Didn't find class "java.net.StandardProtocolFamily" on path: DexPathList[[zip file "/data/app/com.example.victor.zeromqrabbitmq-1/base.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.example.victor.zeromqrabbitmq-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.example.victor.zeromqrabbitmq-1/lib/arm, /vendor/lib, /system/lib]] 
      at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) 
      at java.lang.ClassLoader.loadClass(ClassLoader.java:511) 
      at java.lang.ClassLoader.loadClass(ClassLoader.java:469) 
      at zmq.io.net.tcp.TcpAddress.family(TcpAddress.java:50) 
      at zmq.io.net.tcp.TcpListener.setAddress(TcpListener.java:171) 
      at zmq.SocketBase.bind(SocketBase.java:363) 
      at org.zeromq.ZMQ$Socket.bind(ZMQ.java:2333) 
      at com.example.victor.zeromqrabbitmq.ZeroMQServer.doInBackground(ZeroMQServer.java:24) 
      at com.example.victor.zeromqrabbitmq.ZeroMQServer.doInBackground(ZeroMQServer.java:10) 
      at android.os.AsyncTask$2.call(AsyncTask.java:295) 
      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
      at java.lang.Thread.run(Thread.java:818) 
      Suppressed: java.lang.ClassNotFoundException: java.net.StandardProtocolFamily 
      at java.lang.Class.classForName(Native Method) 
      at java.lang.BootClassLoader.findClass(ClassLoader.java:781) 
      at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) 
      at java.lang.ClassLoader.loadClass(ClassLoader.java:504) 
        ... 13 more 
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available 
09-01 00:44:20.699 13082-13206/com.example.victor.zeromqrabbitmq E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb810d418 

Cela ressemble à une simple erreur classNotFound, mais elle fait référence à une classe fournie avec "android package", ce qui signifie qu'elle n'appartient à aucune bibliothèque externe. Alors, comment pourrait-il ne pas être trouvé?

+1

Si l'application se ferme, une erreur doit se produire dans logcat. Postez-le. –

+1

Fait, logcat posté –

Répondre

0

Le problème que vous rencontrez est la version de JeroMQ que vous utilisez n'est pas compatible avec Android. Cette demande de tirage: https://github.com/zeromq/jeromq/pull/471 a ajouté le support pour Android 10 et au-dessus mais seulement disponible sur 0.4.3-SNAPSHOT.

0

retirer Peut-être le * et le remplacer par localhost

+0

Déjà essayé, problème toujours là. –

0

Règle 0) Habituez-vous à utiliser toujours un appel à une méthode Poller.poll(aTimeoutInMILLISECONDs), de manière à rester en contrôle de ce que les événements doivent être servis (le cas échéant) au sein d'un éco-système en boucle d'événements externes

règle 1) Ne jamais utiliserREQ/REP dans un grave, le code de qualité de production, because of it's inherent hard-wired affinity to fall into an un-salvageable mutual dead-lock.

Règle 2) Toujours préférer une adresse explicite .bind() -s. Les extensions implicites et génériques ne sont pas un moyen pour un déploiement de production, car votre système dépendra des traductions externes - plutôt une adresse explicite et globalement annoncée (même si les exemples de manuels scolaires montrent d'autres pratiques ...)

règle 3) ne hésitez pas à utiliser assert(); ou try:/except: pratique de manipulation, de sorte que vous pouvez localisent bien assez et diagnostiquer la cause d'une exception.Les outils d'erreur ZeroMQ sont disponibles dans la plupart des liaisons de langue.

+0

Veuillez expliquer la règle 2. Relier les serveurs à 0.0.0.0 est la pratique habituelle et ne dépend pas de traductions externes. – EJP

+0

ZeroMQ peut '.bind()' sur de nombreux points cibles '' transport-class: // address: port' ** en même temps, en utilisant un caractère générique. Alors que la syntaxe le permet, tout cas de collision reste "masqué"/"caché" derrière le "troupeau". Donc, en utilisant un explicite, '.bind()' -target est une meilleure pratique, car une gestion d'exception (c'est-à-dire sur une collision de ressources en usage et al) est toujours a priori isolé et sur place pour Introduire un gestionnaire d'exception contextuelle. – user3666197

+0

Je n'étais pas au courant de ces pratiques, puisque je suis nouveau à MQ en général. Mais je vais essayer de garder cela à l'esprit tout en améliorant mon code. Merci! –