application de communication – serveur via socket

Bonjour!

Je programme une application en tant que client à un serveur en utilisant
pour communiquer prises.
Le serveur est une application Java pur qui commence par « java ServerC »
est. Pour tester, j'attachais le smartphone via USB à l'ordinateur portable, qui
est mon réseau local et contient le serveur dans une boîte DOS.
L'application génère automatiquement des clics sur les images de la caméra, puis les envoie
au serveur, qui stocke le répertoire courant. cela fonctionne
au départ. Maintenant, je vous enverrai du serveur pour fournir une rétroaction au client lorsque
l'image a été enregistrée. Ici, les pauses client (App) avec
"douille fermée" à partir de laquelle le retour d'information doit être lue.
Comment cela peut-il être corrigé?
Code client:

de.carpelibrum.camera paquet;importation android.app.Activity;importation android.hardware.Camera;importation android.os.Bundle;importation android.os.SystemClock;importation android.util.Log;importation android.view.MotionEvent;importation android.view.SurfaceHolder;importation android.view.SurfaceView;importation android.view.View;importation android.view.inputmethod.InputMethodManager;importation android.widget.EditText;importation java.io.BufferedInputStream;importation java.io.BufferedOutputStream;importation java.io.IOException;importation java.io.InputStream;importation java.io.OutputStream;importation java.net.Socket;importation java.text.SimpleDateFormat;import java.util.Date;importation java.util.Timer;importation java.util.TimerTask;CameraActivityC public class étend les outils d'activitéSurfaceHolder.Callback,Camera.PictureCallback {finale privée chaîne TAG = "carpelibrum";caméra caméra privée;caméra Camera.PictureCallback privée aperçu de rappel;caméra Camera.ShutterCallback privée de fermeture de rappel;titulaire privé vue de la caméra Holder surface;Surface Voir vue de la caméra;ed EditText;Minuterie t;Chaîne params;int beg = 1000; // commencer intervallerépétition = 5000 int; // intervalle de répétitionbooléen edOkay = false;socket client de douille;boolean rueckMeld = true; // retour d'information à partir du serveurboolean nextImg = true;@Overridepublic void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState);//getWindow().setFormat(PixelFormat.TRANSLUCENT);setContentView (R.layout.main);ed = (EditText) findViewById (R.id.textView1);/ *ed.setOnKeyListener (nouveau View.OnKeyListener () {OnKey public boolean (Voir v, int codeTouche, événement KeyEvent) {si (event.getAction () == KeyEvent.ACTION_DOWN) {Switch (codeTouche) {KeyEvent.KEYCODE_ENTER cas:hideKeyboard (CameraActivityC.this); // retirer le clavier soupleChaîne sp = ed.getText () toString () sous-chaîne (8) ..;Chaîne ca [] = sp.split (".");beg = Integer.parseInt (CA [0]); // commencer intervallerépéter = Integer.parseInt (ca [1]); // intervalle de répétitionLog.d ("****** paramètres:", Sp);ed.setVisibility (View.GONE); // Supprimer EditTextedOkay = true;t = new Timer ();// répété automatiquement à partir ObtainMotionEventt.schedule (nouvelle minuterie (), beg, répétition); // 1000,5 * 1000);return true;par défaut:break;}}return false;}});* /test (); // test simplifié}test de vide () {ed.setVisibility (View.GONE); // Supprimer EditTextedOkay = true;t = new Timer ();// répété automatiquement à partir ObtainMotionEventt.schedule (nouvelle minuterie (), 1000,5 * 1000); // 1000,5 * 1000);}// Interface 1 [email protected] void surface créée (surface porte-Holder) {caméra = Camera.open ();}@Overridepublic void surface modifiée (porte-porteur de surface, la taille de l'int, int largeur,hauteur int) {camera.stopPreview ();Camera.Parameters params = camera.getParameters ();params.setPreviewSize (largeur, hauteur);camera.setParameters (params);try {camera.setPreviewDisplay (support);} Catch (IOException e) {Log.d (TAG, "surF: "+ E.getMessage ());}camera.startPreview ();}@Overridepublic void surfaceDestroyed (porte-superficiaire) {}// Interface Fin [email protected] public boolean (mouvements) {return true si (edOkay!); // confirmation par EditText manquantesi (event.getAction () == MotionEvent.ACTION_UP) {camera.takePicture (this.cameraCallbackVerschluss, this.cameraCallbackVorschau, Ce); onPictureTaken //return true;}else {retourner super.onTouchEvent (event);}}// Interface 2 [email protected] void onPictureTaken (octet [] données, appareil photo de l'appareil photo) {try {// nom ou l'adresse IP du serveursocket client = new Socket ("acer_laptop", 45678); // serveur et le portLog.i ("OnPic_client1", ClientSocket.toString ());OutputStream out = new BufferedOutputStream (clientSocket.getOutputStream ());// pour la rétroaction à partir du serveurInputStream in = new BufferedInputStream (clientSocket.getInputStream ());byte [] b2 = new byte [6];SimpleDateFormat df = new SimpleDateFormat ("aaaa_MM_jj_HH_mm_ss");// remplacer la partie 1 par nom d'utilisateur, qui sert également un sous-répertoire sur le serveurChaîne FNAME = "photo_" + Df.format (new Date ()) +".jpg";out.write (fname.length ());out.write (fname.getBytes ());out.write (données);out.flush ();out.close ();nextImg = false;// *** retour du serveursi (rueckMeld) {Log.i ("OnPic_client2 fermé:". "" + ClientSocket.isClosed ());Log.i ("OnPic_client3", ClientSocket.toString ());// socket client est pas fermé!lire // commentaires de test à partir du serveurint rc = in.read (b2); // vient ici l'erreur "douille fermée"Log.i (TAG, "Message du serveur:" + Rc);nextImg = true;}nextImg = false;camera.startPreview ();} Catch (Exception ex) {Log.e ("Ex_OnPicclient4:", Ex.getMessage ()); // douille fermée// mais pas socket client!Log.e ("Ex_OnPic_client5:", ClientSocket.isClosed () +"."+ ClientSocket.toString ());ex.printStackTrace ();t.cancel ();finition ();}}// interface fin [email protected] protected void () {super.onPause ();si (appareil photo! = null) {// camera.stopPreview ();camera.release ();Log.d (TAG,"Break!");si (t = null!) t.cancel (); // Fin de tâche minuterie}}@OverrideonResume protégé void () {super.onResume ();vue de la caméra = (Affichage de surface) findViewById (R.id.surfaceview1);Porte-vue de la caméra cameraView.getHolder = ();cameraViewHolder.addCallback (ce); Interface // 1cameraViewHolder.setType (SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);caméra rappel aperçu = new Camera.PictureCallback () {public void onPictureTaken (octet [] Données, appareil photo c) {}};caméra verrouillage de rappel = new Camera.ShutterCallback () {onShutter public void () {}};}// Création d'un événement de mouvementannuler ObtainMotionEvent (Voir surface sv) {// non utilisé si (false) {// si (socket client! = Null) {boolean clientSocket.isClosed tc = ();Log.e ("*** Obt_client fermé:". "" + Tc);if (! tc) {// serveur fonctionne toujours sur l'image précédenteretour;}}à long temps d'arrêt = SystemClock.uptimeMillis ();longue durée de l'événement = SystemClock.uptimeMillis () + 100;flotter x = 50.0f;float y = 100.0f;// Liste des états méta trouvés ici: developer.android.com/reference/android/view/KeyEvent.html#getMetaState ()int metaState = 0; // KEY_DOWNévénement de mouvement MotionEvent = MotionEvent.obtain (temps d'arrêt,heure de l'événement,MotionEvent.ACTION_UP,x,y,metaState);sv.dispatchTouchEvent (événement de mouvement); // peut-être. inutileonTouchEvent (événement de mouvement); // envoyer des événements de mouvement}// génération cyclique et l'évaluation d'une touche Eventsminuterie de classe étend TimerTask {public void run () {try {ObtainMotionEvent (vue de l'appareil photo);} Catch (Exception e) {e.printStackTrace ();}}}// clavier souple pour EditText supprimer KEYCODE_ENTERhideKeyboard public static void (activité d'activité) {Gestionnaire de méthode d'entrée imm = (Input Method Manager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE);// Trouver la vue actuellement ciblée, afin que nous puissions corriger le jeton de fenêtre tombe de lui.Voir vue = activity.getCurrentFocus ();// Si aucune vue est actuellement le focus, créer un nouveau, afin que nous puissions tombe un jeton de fenêtre de celui-ciif (voir == null) {= New vue Vue (activité);}imm.hideSoftInputFromWindow (view.getWindowToken (), 0);}}}

Code Serveur:

importation java.io.BufferedInputStream;java.io.FileOutputStream d'importation;importation java.io.IOException;importation java.io.InputStream;importation java.io.OutputStream;importation java.io.PrintStream;importation java.net.ServerSocket;importation java.net.Socket;importation java.text.DecimalFormat;public class {ServerC// int statique DRL2 = 0;public static void main (String [] args) throws IOException {socket serveur du serveur de socket serveur = new Socket (45678);clients = 0 int;System.out.println ("... a commencé serveur d'attente pour les connexions client");while (true) {ServerThreadC server = nouveau thread ServerThreadC (serverSocket.accept () ++ clients);serverThread.start ();System.out.println ("... en attendant plus de connexions clients");}}}classe ServerThreadC extends Thread {int DRL2 = 0 statique;socket client de douille;InputStream;os PrintStream;Sortie ots de flux;int nr;boolean rueckMeld = true;// int DRL2 = 0;byte [] b = new byte [4096];ServerThreadC public (socket client Socket, int nr) lève IOException {this.clientSocket = socket client;System.out.println ("OnPic_client:"+ ClientSocket.toString ());this.nr = nr;en = new BufferedInputStream (clientSocket.getInputStream ());ots = clientSocket.getOutputStream ();// os = nouveau flux d'impression (clientSocket.getOutputStream ());System.out.println ("... client connecté:"+ ClientSocket.getInetAddress ());}public void run () {FileOutputStream out = null;byte [] b = new byte [4096];Chaîne FNAME ="";int DRL = 0;int len;longue start = System.currentTimeMillis ();try {while ((len = in.read (b))>0) {si (DRL ++ == 0) {// Bloc 1: Longueur | nom | donnéesint Le = b [0];byte [] tf = new byte [le];System.arraycopy (b, 1, tf, 0, le);fname = new String (tf); // nom de fichierout = new FileOutputStream (fname);out.write (b, le + 1, LEN-le-1); // envoyer une partie de données/ *if (++ DRL2 < 2) {System.out.println ("... avant de dormir");ServerThread.sleep (10000);System.out.println ("... dormir");}* /continuer;}out.write (b, 0, len);}out.flush ();out.close ();System.out.println ("fermé 1clientSocket ???"+ ClientSocket.isClosed ());si (rueckMeld) {// os.println ("Sortie terminée:" Fname +); // *** sortie au clientots.write (1);System.out.println ("Sortie terminée:"Fname +);System.out.println ("fermé 1clientSocket ???"+ ClientSocket.isClosed ());} Else {// clientSocket.close ();System.out.println ("sans problème Rueck complété:"Fname +);System.out.println ("fermé 2clientSocket ???"+ ClientSocket.isClosed ());}// flux de sortie ots = clientSocket.getOutputStream ();// ots.write (1);Double D = (System.currentTimeMillis () - start) /1000.0;DecimalFormat df = new DecimalFormat ("##. ##");// System.out.println ("socket client fermé:"+ Df.format (d));} Catch (Exception ex) {ex.printStackTrace ();}}}

Modifier Mod Ludy: le code plus lisible conçu


Bonjour Wiki11,

Votre code est très difficile à lire et pas si bien couvert.

Je raccourcissent de: Exception ce que vous obtenez comme une raison spécifiée si la socket a été fermé ..
I.d.R. il est parce que le serveur pour la prise quand il ne considère plus la de plus acceptée comme valide.

Pourquoi le détour via un ordinateur portable? Mais vous pouvez directement connecter au serveur du réseau local
faire une IP fixe ..

Je POUVAIT immédiatement post-scriptum poignées de main dans vos expressions du visage identifier - a une raison?


Je me demande aussi pourquoi le code est difficile à lire, même si je "insérer le code source" ont appuyé.
L'ordinateur portable est mon serveur, téléphone intelligent (avec l'application) et un ordinateur portable sont sur le même réseau.
L'exception est "douille fermée" et est utilisé dans l'instruction de lecture dans l'application:

InputStream in = new BufferedInputStream (clientSocket.getInputStream ());
...
lire // commentaires de test à partir du serveur
// à ce stade: Test si socket client est fermé: pas fermé
int rc = in.read (b2); // vient ici l'erreur "douille fermée"

Vous voulez dire avec une touche poignée de main nen sur l'écran de l'appareil photo?
Étant donné que la fonction ObtainMotionEvent est appelée par minuterie qui génère un programme événement tactile.

Pour imiter ici encore AndroidManifest et main.xml:

xmlns: android ="http://schemas.android.com/apk/res/android"
package ="de.carpelibrum.camera"
android: code version ="1"
android: Nom Version ="1.0">
android: minSdkVersion ="8" android: targetSdkVersion ="8"/>
android: name ="android.permission.CAMERA">
android: name ="android.permission.INTERNET">
android: name ="android.permission.CAMERA">
android: name ="android.hardware.camera"
= Requis: android"vrai" />


xmlns: android ="http://schemas.android.com/apk/res/android"
android: layout_width ="fill_parent"
android: layout_height ="fill_parent"
Applications: orientation ="vertical">
android: layout_height ="wrap_content"
android: id ="@ + Id / linearLayout1"
android: layout_width ="match_parent">
android: text ="beg, représentant: 1000.5000"
android: id ="@ + Id / textView1"
android: layout_width ="wrap_content"
android: layout_height ="wrap_content">

salutation Wicki


Votre erreur est bien sûr aucune cause évidente de l'erreur dans le code source, donc ici vous avez un peu
procéder selon le processus d'élimination.

Je ferais deux premières choses:

L'ordinateur portable est mon serveur, téléphone intelligent (avec l'application) et un ordinateur portable sont sur le même réseau.
L'exception est "douille fermée" et est utilisé dans l'instruction de lecture dans l'application:

a) Votre conception est très inhabituel:
Peg les temps de chose hors, cravate en Wi-Fi avec un IP et et regardez ce qui se passe fixe.
(Si l'ordinateur portable et l'ordinateur sur lequel fonctionne AS ???)

b) Pour être sûr, tout sortir du fil, et seulement quelques fois d'octets pousser à travers la région.
Il se pourrait bien que la douille est adoptée par les différents fils (par exemple, le fil de l'interface utilisateur)

d) Avec Handshake je veux dire une réponse vraiment rudimentaire (et important).
(Vous envoyez quelque chose, le serveur répond - et vice-versa)


Merci pour votre problème!
Sur l'ordinateur portable fonctionne AS, ont scellé téléphone intelligent de l'ordinateur portable, résultat:
l'envoi de la première image est réussie et le serveur (ordinateur portable) correctement stocké, à savoir serveurs d'applications ont une autre connexion.
Le serveur envoie également sa réponse, mais lors de la lecture dans le smartphone est l'exception.
Si je laisse l'envoi de réponse, plus de photos sont facilement transmises et stockées par le serveur.

Voici le journal du serveur:
C: \ Users \ Ad \ AndroidStudioProjects \ Activité de l'appareil photo \ app \ src \ main \ java>java ServerC
... commencé serveur, attente pour les connexions client
OnPic_client: Socket [adr = / 192.168.2.103, port = 38292, port local = 45678]
... connecté Client: /192.168.2.103
... en attendant plus de connexions clients
1clientSocket fermé ??? faux
Sortie terminée: foto_2017_06_23_03_02_07.jpg
1clientSocket fermé ??? faux

Peut-il que le serveur utilise un port différent de celui entre deux convenu à l'origine?

salutation Wicki