2009-03-03 6 views
1

Je veux recevoir un fichier du port série et je dois utiliser ce protocole X-modem est conçu pour recevoir un fichier sur le port série en Java. Donc, si quelqu'un peut avoir une idée sur alors plz m'aider. Je suis dans beaucoup de problèmes.plzMise en œuvre du protocole X-modem en Java

Répondre

1

SerialIO a une implémentation commerciale.

+0

Je dois développer mon propre code. Y at-il une API disponible? –

1

Eh bien ... Il suffit de lire the specs, et de l'implémenter. Cela n'a pas l'air trop difficile, bien qu'en général il peut être difficile de fouiller au niveau des octets en Java.

Je n'ai pas beaucoup cherché pour les implémentations existantes, je suis sûr qu'il y en a plus que le commercial proposé par kgiannakakis, il y en a habituellement. :) Sinon, peut-être prendre un peu de recul, et obtenir une source C à regarder et à ré-implémenter en Java (la licence le permet, bien sûr).

4

La voici. J'ai trouvé cela dans le JModem source. Si vous regardez où il écrit les données, vous pouvez le voir en train de faire un SOH, un blocknum, un ~ blocknum, des données et une somme de contrôle. Il utilise une taille de secteur de 128. Ceux-ci forment ensemble la norme XModem protocol. C'est assez simple pour faire XModem1K, YModem et ZModem d'ici aussi.

/** 
* a tiny version of Ward Christensen's MODEM program for UNIX. 
* Written ~ 1980 by Andrew Scott Beals. Last revised 1982. 
* A.D. 2000 - dragged from the archives for use in Java Cookbook. 
* 
* @author C version by Andrew Scott Beals, sjobrg.andy%[email protected] 
* @author Java version by Ian F. Darwin, [email protected] 
* $Id: TModem.java,v 1.8 2000/03/02 03:40:50 ian Exp $ 
*/ 
class TModem { 

    protected final byte CPMEOF = 26;  /* control/z */ 
    protected final int MAXERRORS = 10;  /* max times to retry one block */ 
    protected final int SECSIZE = 128;  /* cpm sector, transmission block */ 
    protected final int SENTIMOUT = 30;  /* timeout time in send */ 
    protected final int SLEEP = 30;  /* timeout time in recv */ 

    /* Protocol characters used */ 

    protected final byte SOH = 1; /* Start Of Header */ 
    protected final byte EOT = 4; /* End Of Transmission */ 
    protected final byte ACK = 6; /* ACKnowlege */ 
    protected final byte NAK = 0x15; /* Negative AcKnowlege */ 

    protected InputStream inStream; 
    protected OutputStream outStream; 
    protected PrintWriter errStream; 

    /** Construct a TModem */ 
    public TModem(InputStream is, OutputStream os, PrintWriter errs) { 
     inStream = is; 
     outStream = os; 
     errStream = errs; 
    } 

    /** Construct a TModem with default files (stdin and stdout). */ 
    public TModem() { 
     inStream = System.in; 
     outStream = System.out; 
     errStream = new PrintWriter(System.err); 
    } 

    /** A main program, for direct invocation. */ 
    public static void main(String[] argv) throws 
     IOException, InterruptedException { 

     /* argc must == 2, i.e., `java TModem -s filename' */ 
     if (argv.length != 2) 
      usage(); 

     if (argv[0].charAt(0) != '-') 
      usage(); 

     TModem tm = new TModem(); 
     tm.setStandalone(true); 

     boolean OK = false; 
     switch (argv[0].charAt(1)){ 
     case 'r': 
      OK = tm.receive(argv[1]); 
      break; 
     case 's': 
      OK = tm.send(argv[1]); 
      break; 
     default: 
      usage(); 
     } 
     System.out.print(OK?"Done OK":"Failed"); 
     System.exit(0); 
    } 

    /* give user minimal usage message */ 
    protected static void usage() 
    { 
     System.err.println("usage: TModem -r/-s file"); 
     // not errStream, not die(), since this is static. 
     System.exit(1); 
    } 

    /** If we're in a standalone app it is OK to System.exit() */ 
    protected boolean standalone = false; 
    public void setStandalone(boolean is) { 
     standalone = is; 
    } 
    public boolean isStandalone() { 
     return standalone; 
    } 

    /** A flag used to communicate with inner class IOTimer */ 
    protected boolean gotChar; 

    /** An inner class to provide a read timeout for alarms. */ 
    class IOTimer extends Thread { 
     String message; 
     long milliseconds; 

     /** Construct an IO Timer */ 
     IOTimer(long sec, String mesg) { 
      milliseconds = 1000 * sec; 
      message = mesg; 
     } 

     public void run() { 
      try { 
      Thread.sleep(milliseconds); 
      } catch (InterruptedException e) { 
      // can't happen 
      } 
      /** Implement the timer */ 
      if (!gotChar) 
      errStream.println("Timed out waiting for " + message); 
      die(1); 
     } 
    } 

    /* 
    * send a file to the remote 
    */ 
    public boolean send(String tfile) throws IOException, InterruptedException 
    { 
     char checksum, index, blocknumber, errorcount; 
     byte character; 
     byte[] sector = new byte[SECSIZE]; 
     int nbytes; 
     DataInputStream foo; 

     foo = new DataInputStream(new FileInputStream(tfile)); 
     errStream.println("file open, ready to send"); 
     errorcount = 0; 
     blocknumber = 1; 

     // The C version uses "alarm()", a UNIX-only system call, 
     // to detect if the read times out. Here we do detect it 
     // by using a Thread, the IOTimer class defined above. 
     gotChar = false; 
     new IOTimer(SENTIMOUT, "NAK to start send").start(); 

     do { 
      character = getchar(); 
      gotChar = true; 
      if (character != NAK && errorcount < MAXERRORS) 
       ++errorcount; 
     } while (character != NAK && errorcount < MAXERRORS); 

     errStream.println("transmission beginning"); 
     if (errorcount == MAXERRORS) { 
      xerror(); 
     } 

     while ((nbytes=inStream.read(sector))!=0) { 
      if (nbytes<SECSIZE) 
       sector[nbytes]=CPMEOF; 
      errorcount = 0; 
      while (errorcount < MAXERRORS) { 
       errStream.println("{" + blocknumber + "} "); 
       putchar(SOH); /* here is our header */ 
       putchar(blocknumber); /* the block number */ 
       putchar(~blocknumber); /* & its complement */ 
       checksum = 0; 
       for (index = 0; index < SECSIZE; index++) { 
        putchar(sector[index]); 
        checksum += sector[index]; 
       } 
       putchar(checksum); /* tell our checksum */ 
       if (getchar() != ACK) 
        ++errorcount; 
       else 
        break; 
      } 
      if (errorcount == MAXERRORS) 
       xerror(); 
      ++blocknumber; 
     } 
     boolean isAck = false; 
     while (!isAck) { 
      putchar(EOT); 
      isAck = getchar() == ACK; 
     } 
     errStream.println("Transmission complete."); 
     return true; 
    } 

    /* 
    * receive a file from the remote 
    */ 
    public boolean receive(String tfile) throws IOException, InterruptedException 
    { 
     char checksum, index, blocknumber, errorcount; 
     byte character; 
     byte[] sector = new byte[SECSIZE]; 
     DataOutputStream foo; 

     foo = new DataOutputStream(new FileOutputStream(tfile)); 

     System.out.println("you have " + SLEEP + " seconds..."); 

     /* wait for the user or remote to get his act together */ 
     gotChar = false; 
     new IOTimer(SLEEP, "receive from remote").start(); 

     errStream.println("Starting receive..."); 
     putchar(NAK); 
     errorcount = 0; 
     blocknumber = 1; 
     rxLoop: 
     do { 
      character = getchar(); 
      gotChar = true; 
      if (character != EOT) { 
       try { 
        byte not_ch; 
        if (character != SOH) { 
         errStream.println("Not SOH"); 
         if (++errorcount < MAXERRORS) 
          continue rxLoop; 
         else 
          xerror(); 
        } 
        character = getchar(); 
        not_ch = (byte)(~getchar()); 
        errStream.println("[" + character + "] "); 
        if (character != not_ch) { 
         errStream.println("Blockcounts not ~"); 
         ++errorcount; 
         continue rxLoop; 
        } 
        if (character != blocknumber) { 
         errStream.println("Wrong blocknumber"); 
         ++errorcount; 
         continue rxLoop; 
        } 
        checksum = 0; 
        for (index = 0; index < SECSIZE; index++) { 
         sector[index] = getchar(); 
         checksum += sector[index]; 
        } 
        if (checksum != getchar()) { 
         errStream.println("Bad checksum"); 
         errorcount++; 
         continue rxLoop; 
        } 
        putchar(ACK); 
        blocknumber++; 
        try { 
         foo.write(sector); 
        } catch (IOException e) { 
         errStream.println("write failed, blocknumber " + blocknumber); 
        } 
       } finally { 
       if (errorcount != 0) 
        putchar(NAK); 
      } 
     } 
     } while (character != EOT); 

     foo.close(); 

     putchar(ACK); /* tell the other end we accepted his EOT */ 
     putchar(ACK); 
     putchar(ACK); 

     errStream.println("Receive Completed."); 
     return true; 
    } 

    protected byte getchar() throws IOException { 
     return (byte)inStream.read(); 
    } 

    protected void putchar(int c) throws IOException { 
     outStream.write(c); 
    } 

    protected void xerror() 
    { 
     errStream.println("too many errors...aborting"); 
     die(1); 
    } 

    protected void die(int how) 
    { 
     if (standalone) 
      System.exit(how); 
     else 
      System.out.println(("Error code " + how)); 
    } 
} 
+0

@sumesh a fait ce travail pour vous? –

0

Ce programme fonctionne-t-il vraiment? J'essaie de l'utiliser, mais je reçois une exception tout le temps. Dans la partie envoi, le code n'utilise pas du tout le nom de fichier ...

Si vous utilisez JModem, lorsque vous cliquez sur le bouton de transfert, l'autre extrémité reçoit la chaîne "tmodem -r at.ht" ou - s si vous recevez. Mais je ne vois pas cette fin faire quoi que ce soit avec la chaîne ... c'est seulement montré sur la zone de texte ...