Differenze tra le versioni di "Usare uno pseudoterminale per far comunicare bidirezionalmente due programmi"

Da Gambas-it.org - Wikipedia.
 
Riga 6: Riga 6:
  
  
 
+
===Esempio pratico===
 
Nell'esempio che segue, abbiamo i codici di un programma ''Master'' e di un programma ''Slave'', entrambi in linguaggio Gambas, ciascuno dei quali invia dati all'altro e riceve dati dall'altro.
 
Nell'esempio che segue, abbiamo i codici di un programma ''Master'' e di un programma ''Slave'', entrambi in linguaggio Gambas, ciascuno dei quali invia dati all'altro e riceve dati dall'altro.
  
 
Va lanciato prima il programma ''Master'', poi il programma ''Slave''.
 
Va lanciato prima il programma ''Master'', poi il programma ''Slave''.
  
 
+
====Il codice del programma ''Master''====
 
Il codice del programma ''Master'' è il seguente:
 
Il codice del programma ''Master'' è il seguente:
 
  Library "libc:6"
 
  Library "libc:6"
Riga 36: Riga 36:
 
   Dim introitus, exitus As String
 
   Dim introitus, exitus As String
 
    
 
    
    fl = Open "/dev/ptmx" For Read Write
+
  fl = Open "/dev/ptmx" For Read Write
 
      
 
      
 
  <FONT Color=gray>' ''Accesso di grant al programma 'Slave':''</font>
 
  <FONT Color=gray>' ''Accesso di grant al programma 'Slave':''</font>
    i = grantpt(fl.Handle)
+
  i = grantpt(fl.Handle)
    If i < 0 Then Error.Raise("Errore alla funzione 'grantpt()' !")
+
  If i < 0 Then Error.Raise("Errore alla funzione 'grantpt()' !")
 
      
 
      
 
  <FONT Color=gray>' ''Sblocca il programma 'Slave':''</font>
 
  <FONT Color=gray>' ''Sblocca il programma 'Slave':''</font>
    i = unlockpt(fl.Handle)
+
  i = unlockpt(fl.Handle)
    If i < 0 Then Error.Raise("Errore alla funzione 'unlockpt()' !")
+
  If i < 0 Then Error.Raise("Errore alla funzione 'unlockpt()' !")
 
      
 
      
 
  <FONT Color=gray>' ''Ottiene il percorso del programma 'Slave':''</font>
 
  <FONT Color=gray>' ''Ottiene il percorso del programma 'Slave':''</font>
    i = ptsname_r(fl.Handle, percorsoSlave, percorsoSlave.Count)
+
  i = ptsname_r(fl.Handle, percorsoSlave, percorsoSlave.Count)
    If i < 0 Then Error.Raise("Errore alla funzione 'ptsname_r()' !")
+
  If i < 0 Then Error.Raise("Errore alla funzione 'ptsname_r()' !")
 
      
 
      
    Print "Uso del file pts: "; String@(percorsoSlave.Data); "  (da riportare in 'Open' del programma 'Slave')"
+
  Print "Uso del file pts: "; String@(percorsoSlave.Data); "  (da riportare in 'Open' del programma 'Slave')"
 +
 
 +
  exitus = "master"
 
      
 
      
     exitus = "master"
+
  Do
 +
     Read #fl, introitus, -256
 +
    If Len(introitus) > 0 Then
 +
      Print "Lettura"
 +
      Print "Letti "; Len(introitus); " byte: "; introitus
 +
      Print
 +
      Print "Scrittura: "; exitus
 +
      Write #fl, exitus
 +
      Print "Scritti "; Len(exitus); " byte\n"
 +
    Endif
 +
    Wait 1
 +
  Loop
 
      
 
      
    While True
+
  fl.Close
   
+
 
      Read #fl, introitus, -256
 
      If Len(introitus) > 0 Then
 
        Print "Lettura"
 
        Print "Letti "; Len(introitus); " byte: "; introitus
 
        Print
 
        Print "Scrittura: "; exitus
 
        Write #fl, exitus
 
        Print "Scritti "; Len(exitus); " byte\n"
 
      Endif
 
      Sleep 1
 
     
 
    Wend
 
   
 
    fl.Close
 
 
 
 
  '''End'''
 
  '''End'''
  
  
 +
====Il codice del programma ''Slave''====
 
Dopo aver lanciato il programma ''Master'', <SPAN Style="text-decoration:underline">si dovrà avere cura di annotare</span> il file pseudoterminale generato ed utilizzato (mostrato nella console del ''Master''). Il percorso dello pseudoterminale andrà inserito nell'apposita linea di ''Open'' del codice del programma ''Slave'', affinché possa essere aperto in lettura ed in scrittura.
 
Dopo aver lanciato il programma ''Master'', <SPAN Style="text-decoration:underline">si dovrà avere cura di annotare</span> il file pseudoterminale generato ed utilizzato (mostrato nella console del ''Master''). Il percorso dello pseudoterminale andrà inserito nell'apposita linea di ''Open'' del codice del programma ''Slave'', affinché possa essere aperto in lettura ed in scrittura.
<BR>Il codice del programma ''Slave'' è il seguente:
+
 
 +
Il codice del programma ''Slave'' è il seguente:
 
  Library "libc:6"
 
  Library "libc:6"
 
   
 
   
Riga 100: Riga 100:
 
   Dim introitus, exitus As String
 
   Dim introitus, exitus As String
 
    
 
    
    termios = Alloc(60)
+
  termios = Alloc(SizeOf(gb.Byte), 60)
 
      
 
      
 
  <FONT Color=gray>' ''Va inserito il numero del file dello pseudoterminale mostrato nella console del programma "Master":''</font>
 
  <FONT Color=gray>' ''Va inserito il numero del file dello pseudoterminale mostrato nella console del programma "Master":''</font>
    fl = Open "/dev/pts/<FONT Color=red><B>...</b></font>" For Read Write
+
  fl = Open "/dev/pts/<FONT Color=red><B>...</b></font>" For Read Write
 
      
 
      
    i = tcgetattr(fl.Handle, termios)
+
  i = tcgetattr(fl.Handle, termios)
    If i < 0 Then Error.Raise("Errore alla funzione 'tcgetattr()' !")
+
  If i < 0 Then Error.Raise("Errore alla funzione 'tcgetattr()' !")
 
      
 
      
    cfmakeraw(termios)
+
  cfmakeraw(termios)
    tcsetattr(fl.Handle, TCSANOW, termios)
+
  tcsetattr(fl.Handle, TCSANOW, termios)
 
      
 
      
    exitus = "slave"
+
  exitus = "slave"
 
      
 
      
     While True
+
  Do
     
+
     Print "Lettura"
      Print "Lettura"
+
    Read #fl, introitus, -256
      Read #fl, introitus, -256
+
    Print "Letti "; Len(introitus); " byte: "; introitus
      Print "Letti "; Len(introitus); " byte: "; introitus
+
    Print
      Print
+
    Print "Scrittura: "; exitus
      Print "Scrittura: "; exitus
+
    Write #fl, exitus
      Write #fl, exitus
+
    Print "Scritti "; Len(exitus); " byte\n"
      Print "Scritti "; Len(exitus); " byte\n"
+
    Wait 1
      Sleep 1
+
  Loop
     
+
 
    Wend
+
  Free(termios)
   
+
  fl.Close
    Free(termios)
 
    fl.Close
 
 
    
 
    
 
  '''End'''
 
  '''End'''
 
  
  

Versione attuale delle 15:50, 7 dic 2022

L'intenzione è di far comunicare bidirezionalmente mediante l'uso di un file pseudoterminale due programmi: uno Master e l'altro Slave.
In tal caso il programma Master invia dati al programma Slave, il quale riceve detti dati e ne invia altri al programma Master. Più precisamente ogni dato scritto (in uscita) dal programma Master, appare in entrata sul programma Slave; ed ogni dato scritto (in uscita) dal programma Slave, appare in entrata nel programma Master.

I programmi (il Master e lo Slave) possono essere indifferentemente entrambi programmi Gambas, oppure un programma Gambas ed un programma esterno scritto in altro linguaggio.
Si farà comunque uso di alcune funzioni esterne contenute nella libreria libc.so.6 .


Esempio pratico

Nell'esempio che segue, abbiamo i codici di un programma Master e di un programma Slave, entrambi in linguaggio Gambas, ciascuno dei quali invia dati all'altro e riceve dati dall'altro.

Va lanciato prima il programma Master, poi il programma Slave.

Il codice del programma Master

Il codice del programma Master è il seguente:

Library "libc:6"

' int grantpt (int __fd)
' Chown the slave to the calling user.
Private Extern grantpt(__fd As Integer) As Integer
 
' int unlockpt (int __fd)
' Release an internal lock so the slave can be opened.
Private Extern unlockpt(__fd As Integer) As Integer

' int ptsname_r (int __fd, char *__buf, size_t __buflen)
' Store at most BUFLEN characters of the pathname of the slave pseudo
' terminal associated with the master FD is open on in BUF.
Private Extern ptsname_r(__fd As Integer, __buf As Byte[], __buflen As Long) As Integer


Public Sub Main()
 
 Dim fl As File
 Dim i As Integer
 Dim percorsoSlave As New Byte[32]
 Dim introitus, exitus As String
 
 fl = Open "/dev/ptmx" For Read Write
   
' Accesso di grant al programma 'Slave':
 i = grantpt(fl.Handle)
 If i < 0 Then Error.Raise("Errore alla funzione 'grantpt()' !")
   
' Sblocca il programma 'Slave':
 i = unlockpt(fl.Handle)
 If i < 0 Then Error.Raise("Errore alla funzione 'unlockpt()' !")
   
' Ottiene il percorso del programma 'Slave':
 i = ptsname_r(fl.Handle, percorsoSlave, percorsoSlave.Count)
 If i < 0 Then Error.Raise("Errore alla funzione 'ptsname_r()' !")
   
 Print "Uso del file pts: "; String@(percorsoSlave.Data); "  (da riportare in 'Open' del programma 'Slave')"
  
 exitus = "master"
   
 Do
   Read #fl, introitus, -256
   If Len(introitus) > 0 Then 
     Print "Lettura"
     Print "Letti "; Len(introitus); " byte: "; introitus
     Print
     Print "Scrittura: "; exitus
     Write #fl, exitus
     Print "Scritti "; Len(exitus); " byte\n"
   Endif
   Wait 1
 Loop
   
 fl.Close
 
End


Il codice del programma Slave

Dopo aver lanciato il programma Master, si dovrà avere cura di annotare il file pseudoterminale generato ed utilizzato (mostrato nella console del Master). Il percorso dello pseudoterminale andrà inserito nell'apposita linea di Open del codice del programma Slave, affinché possa essere aperto in lettura ed in scrittura.

Il codice del programma Slave è il seguente:

Library "libc:6"

Private Const TCSANOW As Integer = 0

' int tcgetattr (int __fd, struct termios *__termios_p)
' Put the state of FD into *TERMIOS_P.
Private Extern tcgetattr(__fd As Integer, __termios_p As Pointer) As Integer

' void cfmakeraw (struct termios *__termios_p)
' Set *TERMIOS_P to indicate raw mode.
Private Extern cfmakeraw(__termios_p As Pointer)

' int tcsetattr (int __fd, int __optional_actions, const struct termios *__termios_p)
' Set the state of FD to *TERMIOS_P.
Private Extern tcsetattr(__fd As Integer, __optional_actions As Integer, __termios_p As Pointer) As Integer 


Public Sub Main()
 
 Dim termios As Pointer
 Dim fl As File
 Dim i As Integer
 Dim introitus, exitus As String
 
 termios = Alloc(SizeOf(gb.Byte), 60)
   
' Va inserito il numero del file dello pseudoterminale mostrato nella console del programma "Master":
 fl = Open "/dev/pts/..." For Read Write
   
 i = tcgetattr(fl.Handle, termios)
 If i < 0 Then Error.Raise("Errore alla funzione 'tcgetattr()' !")
   
 cfmakeraw(termios)
 tcsetattr(fl.Handle, TCSANOW, termios)
   
 exitus = "slave"
   
 Do
   Print "Lettura"
   Read #fl, introitus, -256
   Print "Letti "; Len(introitus); " byte: "; introitus
   Print
   Print "Scrittura: "; exitus
   Write #fl, exitus
   Print "Scritti "; Len(exitus); " byte\n"
   Wait 1
 Loop
 
 Free(termios)
 fl.Close
  
End


Riferimenti