2017-04-25 4 views
3

Je travaille sur un appareil qui fonctionnerait pour mesurer certaines lectures à travers des capteurs. L'appareil est exploité par une application Android. Je dois prendre des lectures de la couche TCP. Voici le code pour envoyer des données sur TCPComment envoyer un paquet en utilisant le protocole de communication binaire sur le port tcp

TcpClient.java

import android.util.Log; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.net.InetAddress; 
import java.net.Socket; 

/** 
* Created by shahbaz on 25/4/17. 
*/ 

public class TcpClient { 

public static final String SERVER_IP = "192.168.1.76"; //server IP address 
public static final int SERVER_PORT = 1800; 
// message to send to the server 
private String mServerMessage; 
// sends message received notifications 
private OnMessageReceived mMessageListener = null; 
// while this is true, the server will continue running 
private boolean mRun = false; 
// used to send messages 
private PrintWriter mBufferOut; 
// used to read messages from the server 
private BufferedReader mBufferIn; 

/** 
    * Constructor of the class. OnMessagedReceived listens for the messages received from server 
    */ 
public TcpClient(OnMessageReceived listener) { 
    mMessageListener = listener; 
} 

/** 
* Sends the message entered by client to the server 
* 
* @param message text entered by client 
*/ 
public void sendMessage(String message) { 
    if (mBufferOut != null && !mBufferOut.checkError()) { 
     mBufferOut.println(message); 
     mBufferOut.flush(); 
    } 
} 

/** 
* Close the connection and release the members 
*/ 
public void stopClient() { 

    mRun = false; 

    if (mBufferOut != null) { 
     mBufferOut.flush(); 
     mBufferOut.close(); 
    } 

    mMessageListener = null; 
    mBufferIn = null; 
    mBufferOut = null; 
    mServerMessage = null; 
} 

public void run() { 

    mRun = true; 

    try { 
     //here you must put your computer's IP address. 
     InetAddress serverAddr = InetAddress.getByName(SERVER_IP); 

     Log.e("TCP Client", "C: Connecting..."); 

     //create a socket to make the connection with the server 
     Socket socket = new Socket(serverAddr, SERVER_PORT); 

     try { 

      //sends the message to the server 
      mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 

      //receives the message which the server sends back 
      mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream())); 


      //in this while the client listens for the messages sent by the server 
      while (mRun) { 

       mServerMessage = mBufferIn.readLine(); 

       if (mServerMessage != null && mMessageListener != null) { 
        //call the method messageReceived from MyActivity class 
        mMessageListener.messageReceived(mServerMessage); 
       } 

      } 

      Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'"); 

     } catch (Exception e) { 

      Log.e("TCP", "S: Error", e); 

     } finally { 
      //the socket must be closed. It is not possible to reconnect to this socket 
      // after it is closed, which means a new socket instance has to be created. 
      socket.close(); 
     } 

    } catch (Exception e) { 

     Log.e("TCP", "C: Error", e); 

    } 

} 

    //Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity 
    //class at on asynckTask doInBackground 
    public interface OnMessageReceived { 
    public void messageReceived(String message); 
} 

}

packet formatStructure des paquets

format paquet contient, tout en communiquant avec l'appareil TCP, les limites entre les paquets ne sont pas identifiées, dans ce cas si les paquets sont hors séquence ou si l'un des paquets est manqué, on peut identifier un nouveau paquet en utilisant 'header start'. Ainsi, les 2 premiers octets du paquet représentent le début du paquet.

Début de l'en-tête: champ de deux octets qui indique le début de chaque paquet. 0x55AA est un nombre de 2 octets utilisé comme début d'en-tête.

Version du protocole: champ d'un octet pour spécifier la version du protocole utilisé. La version spécifiée dans la charge déterminera la structure de la charge utile. À tout moment, un appareil prend en charge la version à protocole unique. La version actuelle du protocole est "1". DSN: Le numéro de séquence est un champ de 1 octet qui identifie le paquet de façon unique. Le demandeur du paquet devra remplir ce champ dans la charge utile de requête; le répondeur doit remplir le même identificateur unique dans la charge utile de réponse.

ID de la requête: champ d'un octet spécifie l'ID de la commande. L'analyse de la charge utile sera effectuée sur la base de l'ID de commande. En cas de charge utile de requête, ce champ sera non nul et en cas de réponse, il sera nul.

Longueur de la charge utile: champ de deux octets spécifie la longueur de la charge utile en octets. Il spécifie le nombre d'octets suivi du champ de longueur de charge utile. Dans la longueur de la charge utile, la longueur de l'en-tête et le CRC ne sont pas inclus. Actuellement, la longueur de charge utile maximale prise en charge par le périphérique de passerelle est de 512 (octets). CRC: champ de 1 octet qui sera calculé par XORing tous les octets et ajouter le compte XOR de 0.

Et il fonctionne. Mais selon docs je dois envoyer le paquet en utilisant le protocole de communication binaire. Y compris début de l'en-tête, données utiles, etc. Comment puis-je envoyer ces paramètres dans la structure de paquets? Comment puis-je créer un paquet?

Toute aide est appréciée.

+0

partager Cant que doc. Je veux juste savoir comment envoyer ces paramètres –

+1

Puisque vous avez besoin d'envoyer des octets, vous voudrez (probablement) utiliser un DataInputStream et un DataOutputStream. J'utiliserais un tableau d'octets de longueur '7' pour stocker 'Header Start' à' Payload Length'. Puis un autre tableau d'octets, avec une longueur maximale '(2^15)', pour stocker les 'données de charge 'et' CRC'. Je concaténerais alors les deux tableaux dans un tableau d'octets de taille '7 + (2^15)' et j'écrirais ce tableau en utilisant 'DataOutputStream # write (byte [] tableau, int offset, int longueur)', où 'offset' être '0' et' longueur' serait '7 + (2^15)'. Ceci est cependant une approche de très bas niveau. –

+0

Pouvez-vous s'il vous plaît poster une réponse avec quelques codes. Et qu'en est-il des données de charge utile? Quelle serait sa structure –

Répondre

2

La principale erreur était que je ne pensais pas beaucoup à la taille des types de données primitifs.

octet = 1 octet

court = 2 octets

int = 4 octets

longue = 8 octets

flotteur = 4 octets

doubles = 8 octets

omble = 2 octets

Après référence à la taille des types de données primitifs je me suis aperçu que nous devrions suivre la taille et l'indice du paquet parce que nous traitons avec tableau d'octets.

TcpPacket.java

public class TcpPacket { 

private static int header_start = 0x55AA; 

private static int protocol_version = 1; 

private PacketUtils packetUtils = new PacketUtils(); 






public byte[] getHandshakePacket() 
{ 
    int request_id = 1; 

    byte[] header_data = packetUtils.ItoBA2(header_start); 
    byte[] payload_data = packetUtils.ItoBA4(packetUtils.getDateTime()); 
    byte[] payload_length = packetUtils.ItoBA2(4); 


    byte[] a_data = new byte[]{header_data[0], header_data[1], (byte) protocol_version, packetUtils.getDSN(), (byte) request_id, payload_length[0], payload_length[1], 
      payload_data[0], payload_data[1], payload_data[2], payload_data[3]}; 

    byte[] b_data = new byte[]{ packetUtils.getCRC(a_data)}; 

    byte[] packet_data = packetUtils.concatBytes(a_data,b_data); 


    return packet_data; 
} 

} 

PacketUtils.java

public class PacketUtils { 



public byte[] ItoBA4(int value) {  // integer to bytes function (return byte array of 4 bytes) 
    return new byte[] { 
      (byte)(value >>> 24), 
      (byte)(value >>> 16), 
      (byte)(value >>> 8), 
      (byte)value}; 
} 


public byte[] ItoBA2(int value) { // integer to bytes function (return byte array of 2 bytes) 
    return new byte[] { 
      (byte)(value >>> 8), 
      (byte)value}; 
} 


public byte getDSN() // return one byte random number 
{ 
    char[] chars = "1234567890".toCharArray(); 
    StringBuilder sb = new StringBuilder(); 
    Random random = new Random(); 
    for (int i = 0; i < 1; i++) { 
     char c = chars[random.nextInt(chars.length)]; 
     sb.append(c); 
    } 
    byte output = Byte.valueOf(sb.toString()); 
    return output; 
} 



public byte getCRC(byte[] packet) // required CRC function (return byte) 
{ 
    try 
    { 
     if (packet == null) 
     { 
      //Logger.Error("empty packet received"); 
      return (byte)0; 
     } 

     byte XORCheckSum = 0; 
     byte zeroCount = 0; 
     byte FFCount = 0; 

     for (int i = 0; i < packet.length; i++) 
     { 
      XORCheckSum ^= packet[i]; 
      if (packet[i] == (byte) 0) 
      { 
       zeroCount++; 
       continue; 
      } 
      if (packet[i] == (byte)255) 
      { 
       FFCount++; 
       continue; 
      } 
     } 

     XORCheckSum ^= zeroCount; 
     XORCheckSum ^= FFCount; 
     return XORCheckSum; 
    } 
    catch (Exception ex) 
    { 
     //Logger.Error(ex); 
     return (byte)0; 
    } 
} 



byte[] concatBytes(byte[]...arrays)  // concatenate byte arrays 
{ 
    // Determine the length of the result array 
    int totalLength = 0; 
    for (int i = 0; i < arrays.length; i++) 
    { 
     totalLength += arrays[i].length; 
    } 

    // create the result array 
    byte[] result = new byte[totalLength]; 

    // copy the source arrays into the result array 
    int currentIndex = 0; 
    for (int i = 0; i < arrays.length; i++) 
    { 
     System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length); 
     currentIndex += arrays[i].length; 
    } 

    return result; 
} 

public int getDateTime() 
{ 
    int dateInSec = (int) (System.currentTimeMillis()/1000); 
    return dateInSec; 

} 



}