View Full Version : Trasferire file da un pc all'altro mediante MSCOMM (VB)
Ho letto che per trasferire file da un pc all'altro utilizzando la porta seriale e l'oggetto MSCOMM di Visual Basic esiste un certo protocollo "Kermit" . Qualcuno di voi lo ha mai implementato ? Se no , sapreste indicarmi qualche altro procedimento per trasferire file con MSCOMM ? Grazie .
Vi prego aiutatemi !!!!!!! Io avevo anche provato ad implementarmi una sorta di protocollo ma ho avuto diversi problemi . In pratica apro il file di testo in lettura , leggo ogni riga che poi metto sul buffer di uscita . L'altra applicazione riceve la riga e la scrive in un altro file di testo . In teoria la cosa è semplice eppure quando invio mi servirebbe qualcosa che pulisca il buffer di ricezione . Qualcuno ne sa qualcosa ?
Non puoi stare a leggere una riga di testo (perchè per i file binari non va bene)... Ti conviene di più leggere un tot di byte ed inviarli... Fissato il numero di byte non ci dovrebbero essere problemi di pulizia del buffer o di altro (se non per l'ultima trasmissione)...
Potresti ad esempio fare ogni trasmissione composta da un intero seguito dagli altri tot byte fissati letti dal file...
Questo byte può contenere la dimensione dei dati letti dal file (che seguono quell'intero)...
Ad esempio se fissi in 4096 il numero massimo di byte che compongono un pacchetto...ne leggi sempre 4096...
Invii sull'interfaccia l'intero 4096 seguito dai 4096 byte letti...
L'ultima lettura può essere un numero minore di 4096...mettiamo sia 1234...
Invii sull'interfaccia 1234 seguito dai 1234 byte letti...
Se ad esempio il file risulta multiplo di 4096...allora devi anche inviare un pacchetto con l'intero a 0 seguito da nessun byte...
Questa soluzione ti può servire anche per inviare altri comandi (ad esempio il cambio o il contenuto di una directory, la disconnessione)...
Fissando a 4096 il numero massimo (4096 codificato in binario equivale al bit 13 a 1)...ti rimangono altri 18 bit per poter codificare il tuoi comandi (un intero sono 32 bit)...
Originally posted by "cionci"
Non puoi stare a leggere una riga di testo (perchè per i file binari non va bene)... Ti conviene di più leggere un tot di byte ed inviarli... Fissato il numero di byte non ci dovrebbero essere problemi di pulizia del buffer o di altro (se non per l'ultima trasmissione)...
Potresti ad esempio fare ogni trasmissione composta da un intero seguito dagli altri tot byte fissati letti dal file...
Questo byte può contenere la dimensione dei dati letti dal file (che seguono quell'intero)...
Ad esempio se fissi in 4096 il numero massimo di byte che compongono un pacchetto...ne leggi sempre 4096...
Invii sull'interfaccia l'intero 4096 seguito dai 4096 byte letti...
L'ultima lettura può essere un numero minore di 4096...mettiamo sia 1234...
Invii sull'interfaccia 1234 seguito dai 1234 byte letti...
Se ad esempio il file risulta multiplo di 4096...allora devi anche inviare un pacchetto con l'intero a 0 seguito da nessun byte...
Questa soluzione ti può servire anche per inviare altri comandi (ad esempio il cambio o il contenuto di una directory, la disconnessione)...
Fissando a 4096 il numero massimo (4096 codificato in binario equivale al bit 13 a 1)...ti rimangono altri 18 bit per poter codificare il tuoi comandi (un intero sono 32 bit)...
Allora cionci , innanzitutto il file che invio non è un file binario ma un file di testo . Scusami se te lo chiedo , potresti farmi qualche esempio ?
A proposito come faccio a leggere un certo numero di byte ? Anzi come si crea un vero pacchetto ?
Il pacchetto è un serie di byte in memoria (un Array in VB)...
Per costruire il pacchetto non dovrai fare altro che andarti a leggere questa serie di byte sul disco... Ora per fare questo non so VB come si comporti (in teoria usando le API basta aprire il file con CreateFile e leggerlo con ReadFile)...
Mi informo un po' meglio su come si legge un array di una certa dimensione in VB...
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW = 1
Const CREATE_ALWAYS = 2
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'La costante sotto la puoi cambiare per aumentare il numero masismo di byte
Const BYTE_PER_MSG = 16
'Serve solo per simualare l'invio
Private Sub Send(data As Byte)
MsgBox "Byte: " + Str(Int(data))
End Sub
Private Sub SendMsg(num As Long, buf() As Byte)
'Supponi di avere la tua sub che invia un byte alla volta e che si chiami Send
'La prima cosa che bisogna fare è inviare la dimensione del pacchetto
'Gli interi sono 4 byte e di conseguenza vanno scomposti in 4 pacchetti
Dim tmp As Byte, I As Long
tmp = (num And &HFF000000) / &H1000000
Send tmp
tmp = (num And &HFF0000) / &H10000
Send tmp
tmp = (num And &HFF00) / &H100
Send tmp
tmp = num And &HFF
Send tmp
'Per ricostruire il long basta fare in questo modo:
'Dim num As Long, tmp As Byte
'Recv tmp
'num = Int(tmp) * &H1000000
'Recv tmp
'num = num + Int(tmp) * &H10000
'Recv tmp
'num = num + Int(tmp) * &H100
'Recv tmp
'num = num + Int(tmp)
For I = 1 To num
Send buf(I)
Next I
End Sub
Private Sub Command1_Click()
Dim buffer(BYTE_PER_MSG) As Byte, f As Long, read As Long
f = CreateFile("nomefile.txt", GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
If f = -1 Then
MsgBox "Errore nell'apertura del file !!!"
Else
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
MsgBox "Byte letti: " + Str(read)
'Ora richiamo la Sub che invia i dati
SendMsg read, buffer
Loop While read > 0
CloseHandle f
End If
End Sub
Crea un file nomefile.txt nella stessa directory del progetto...
Ricordati che il file è finito quando ricevi un pacchetto con contatore uguale a 0 (ed ovviamente 0 byte che lo seguono)...
Per creare un file in cui scrivere :
CreateFile(nomefile, GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, CREATE_ALWAYS, 0, 0)
Attento che sovrascrive i file già esistenti...
Per scriverci WriteFile e funziona alla stesza maniera della ReadFile...
Scusa cionci , mi spieghi il perché di quelle cifre binarie ? Quella funzione send che simula l'invio , in realtà a cosa dovrei farla corrispondere ? Voglio dire , io con l'oggetto mscomm posso solo inviare stringhe . C'è qualche altra API che invia il pacchetto ?
Credevo che si potessere inviare generalmente byte...
La Send dovrebbe essere la tua funzione che invia un byte alla volta sulla seriale...ho guardato come si fa l'output con Mscomm e puoi inviare anche vettori di byte...
Sinceramente non so come operare con i Variant comunque ci provo...
Allora prova a fare in questo modo diverso :
Private Sub SendMsg(num As Long, buf() As Byte)
Dim tmp(4) As Byte, I As Long
Dim v As Variant
tmp(1) = (num And &HFF000000) / &H1000000
tmp(2) = (num And &HFF0000) / &H10000
tmp(3) = (num And &HFF00) / &H100
tmp(4) = num And &HFF
v = tmp
mscomm1.Output = v
'Non so se buf vada ridimensionato comunque lo faccio uguale
ReDim Preserve buf(num)
v = buf
mscomm1.Output = v
End Sub
num è un intero..quindi 4 byte... Magari lo potrai anche spedire direttamente tramite il Variant, ma non lo so (faid elle prove)... In ogni caso puoi farne un vettore di byte ed inviarlo...
Originally posted by "cionci"
Credevo che si potessere inviare generalmente byte...
La Send dovrebbe essere la tua funzione che invia un byte alla volta sulla seriale...ho guardato come si fa l'output con Mscomm e puoi inviare anche vettori di byte...
Sinceramente non so come operare con i Variant comunque ci provo...
Allora prova a fare in questo modo diverso :
Private Sub SendMsg(num As Long, buf() As Byte)
Dim tmp(4) As Byte, I As Long
Dim v As Variant
tmp(1) = (num And &HFF000000) / &H1000000
tmp(2) = (num And &HFF0000) / &H10000
tmp(3) = (num And &HFF00) / &H100
tmp(4) = num And &HFF
v = tmp
mscomm1.Output = v
'Non so se buf vada ridimensionato comunque lo faccio uguale
ReDim Preserve buf(num)
v = buf
mscomm1.Output = v
End Sub
num è un intero..quindi 4 byte... Magari lo potrai anche spedire direttamente tramite il Variant, ma non lo so (faid elle prove)... In ogni caso puoi farne un vettore di byte ed inviarlo...
Sei magico cionci , ma come diavolo fai a conoscere o a trovare tutte queste informazioni ?
Scusa , ma la variabile variant che vantaggio ha ? se non sbaglio quella di essere ridimenzionata a seconda del tipo di dato ?
Ritronando al discorso dei pacchetti : io apro un file con la funzione ReadFile . A questo punto devo creare pacchetti di quanti byte ?
Originally posted by "leon84"
Scusa , ma la variabile variant che vantaggio ha ? se non sbaglio quella di essere ridimenzionata a seconda del tipo di dato ?
Diciamo che in pratica fa questo...
Originally posted by "leon84"
Ritronando al discorso dei pacchetti : io apro un file con la funzione ReadFile . A questo punto devo creare pacchetti di quanti byte ?
Con ReadFile si legge...
Quanti te ne pare...ma in generale conviene farlo di multipli di 1024...
Io scelgo quasi sempre di 4096, oltre solitamente non si hanno vantaggi, anche se dipende da molti fattori...
Originally posted by "cionci"
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW = 1
Const CREATE_ALWAYS = 2
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'La costante sotto la puoi cambiare per aumentare il numero masismo di byte
Const BYTE_PER_MSG = 16
'Serve solo per simualare l'invio
Private Sub Send(data As Byte)
MsgBox "Byte: " + Str(Int(data))
End Sub
Private Sub SendMsg(num As Long, buf() As Byte)
'Supponi di avere la tua sub che invia un byte alla volta e che si chiami Send
'La prima cosa che bisogna fare è inviare la dimensione del pacchetto
'Gli interi sono 4 byte e di conseguenza vanno scomposti in 4 pacchetti
Dim tmp As Byte, I As Long
tmp = (num And &HFF000000) / &H1000000
Send tmp
tmp = (num And &HFF0000) / &H10000
Send tmp
tmp = (num And &HFF00) / &H100
Send tmp
tmp = num And &HFF
Send tmp
'Per ricostruire il long basta fare in questo modo:
'Dim num As Long, tmp As Byte
'Recv tmp
'num = Int(tmp) * &H1000000
'Recv tmp
'num = num + Int(tmp) * &H10000
'Recv tmp
'num = num + Int(tmp) * &H100
'Recv tmp
'num = num + Int(tmp)
For I = 1 To num
Send buf(I)
Next I
End Sub
Private Sub Command1_Click()
Dim buffer(BYTE_PER_MSG) As Byte, f As Long, read As Long
f = CreateFile("nomefile.txt", GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
If f = -1 Then
MsgBox "Errore nell'apertura del file !!!"
Else
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
MsgBox "Byte letti: " + Str(read)
'Ora richiamo la Sub che invia i dati
SendMsg read, buffer
Loop While read > 0
CloseHandle f
End If
End Sub
Crea un file nomefile.txt nella stessa directory del progetto...
Ricordati che il file è finito quando ricevi un pacchetto con contatore uguale a 0 (ed ovviamente 0 byte che lo seguono)...
Per creare un file in cui scrivere :
CreateFile(nomefile, GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, CREATE_ALWAYS, 0, 0)
Attento che sovrascrive i file già esistenti...
Per scriverci WriteFile e funziona alla stesza maniera della ReadFile...
Scusa cionci , non riesco a capire una cosa : Nell'evento click del pulsante hai dichiarato la variabile buffer . Ma quel buffer è un vettore di 16 elementi in questo caso ? Se si perché poi quando richiami la funzione ReadFile scrivi Buffer(1) ? Utilizzando questa scrittura non significa che le informazioni vengono memorizzate alla posizione 1 del vettore ? Scusami se certe domande ti sembrano banali ma VB lo studio da me ; è a scuola che facciamo C++
Perchè ReadFile vuole il puntatore al primo elemento del buffer...e in VB si fa così ;)
Un'altra cosa : Ma siccome hai detto che l'MSCOMM può anche prendere un vettore di byte , allora perché creare la funzione che li scompone e ne invia uno alla volta ? Non posso semplicemente aprire il file , leggere tot byte ed inviarli col variant nel MSCOMM ?
Originally posted by "leon84"
Un'altra cosa : Ma siccome hai detto che l'MSCOMM può anche prendere un vettore di byte , allora perché creare la funzione che li scompone e ne invia uno alla volta ? Non posso semplicemente aprire il file , leggere tot byte ed inviarli col variant nel MSCOMM ?
Infatti nella versione della SendMsg che ti ho riscritto sopra li spedisco tutti insieme...
Originally posted by "cionci"
Infatti nella versione della SendMsg che ti ho riscritto sopra li spedisco tutti insieme...
Scusa quale ?
Questa:
Private Sub SendMsg(num As Long, buf() As Byte)
Dim tmp(4) As Byte, I As Long
Dim v As Variant
tmp(1) = (num And &HFF000000) / &H1000000
tmp(2) = (num And &HFF0000) / &H10000
tmp(3) = (num And &HFF00) / &H100
tmp(4) = num And &HFF
v = tmp
mscomm1.Output = v
'Non so se buf vada ridimensionato comunque lo faccio uguale
ReDim Preserve buf(num)
v = buf
mscomm1.Output = v
End Sub
Non capisco il perché di queste divisioni
Originally posted by "leon84"
Non capisco il perché di queste divisioni
Perchè un intero è fatto da 4 byte...e io devo assegnare ognuno di questi byte ad una posizione del vettore...
Sai cosa significa fare un AND bit a bit e uno shift (ho utilizzato la divisione al posto dello shift perchè in VB non sapevo come fare) ?
Se non sbaglio AND bit a bit significa che restituisce 1 se entrambi i bit sono 1 e 0 altrimenti giusto ? Lo shift è uno scambio ..... uno spostamento di elementi all'interno del vettore o di una lista dinamica ecc .... se ricordo bene . Ma cmq ancora non riesco a capire perché scomporre i 4 byte . Abbiamo detto che l'invio avviene su di un certo numero di byte , allora perché scomporli . Forse sarò tosto ma proprio non riesco a capirlo
Perchè ho letto che vengono inviati o stringhe o array di byte...ma non un intero e visto che non è convertibile direttamente in un vettore di byte allora lo converto io in un vettore di byte...
Prova a vedere se invia anche l'intero senza metterlo in un vettore di byte...
Originally posted by "cionci"
Perchè ho letto che vengono inviati o stringhe o array di byte...ma non un intero e visto che non è convertibile direttamente in un vettore di byte allora lo converto io in un vettore di byte...
Prova a vedere se invia anche l'intero senza metterlo in un vettore di byte...
Scusa ma ancora non ti seguo . Perché inviare l'intero ? Io apro il file ; leggo tot byte ed invio questi tot byte . Cos'altro devo fare ?
Un'altra cosa . Perché inviare prima la dimensione del pacchetto ? A cosa mi serve ?
Per creare un file in cui scrivere :
CreateFile(nomefile, GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, CREATE_ALWAYS, 0, 0)
Attento che sovrascrive i file già esistenti...
Scusa ma se io il file lo devo aprire per leggerlo come faccio se la create file me lo sovrascrive ? Siccome la ReadFile ha bisogno dell'handle del file c'è qualche altro modo per ottenerlo ?
Su un'altra cosa non mi trovo :
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
Loop While read > 0
La variabile read che hai utilizzato conta il numero di byte letti giusto ? A meno che il file non sia vuoto queste istruzioni creano un ciclo infinito perché e il file che aprò non è vuoto read risulterà sempre maggiore di 0 . Ed infatti avviandolo con VB il programma si alluppa . Ti trovi ? E come dico io o ho interpretato male ?
Originally posted by "leon84"
Scusa ma se io il file lo devo aprire per leggerlo come faccio se la create file me lo sovrascrive ? Siccome la ReadFile ha bisogno dell'handle del file c'è qualche altro modo per ottenerlo ?
Questo era per la creazione del file in cui mettere i dati che ricevi ;) Nell'esempio il file che apro lo apro normalmente (guarda la differenza fra i due metodi)...
Originally posted by "leon84"
Un'altra cosa . Perché inviare prima la dimensione del pacchetto ? A cosa mi serve ?
A sapere quanti byte leggere dopo !!! Altrimenti come fai a saperlo ?!?!?!?
Ah scusa ho capito queste istruzioni commettevo io l'errore . Ma non sarebbe meglio fare così la condizione di uscita ? Così risparmierei un cilco ti trovi ? Quanto alla CreateFile si ho capito , scusami . Poi un'altra cosa , come stanno le cose e siccome l'integer è di 4 byte non posso inviare un file superiore a 32 K ?
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
Loop While read <BYTE_PER_MSG
Originally posted by "leon84"
Su un'altra cosa non mi trovo :
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
Loop While read > 0
La variabile read che hai utilizzato conta il numero di byte letti giusto ? A meno che il file non sia vuoto queste istruzioni creano un ciclo infinito perché e il file che aprò non è vuoto read risulterà sempre maggiore di 0 . Ed infatti avviandolo con VB il programma si alluppa . Ti trovi ? E come dico io o ho interpretato male ?
Strano che ti vada in loop...a meno lo fa...
La ReadFile cerca di leggere BYTE_PER_MSG byte dal file... Il numero di byte letti finisce in read... La posizione da cui si andrà a leggere dopo è quella successiva all'ultimo byte letto...quindi se il file ha una qualsiasi dimensione prima o poi read varrà zero (cioè nel ciclo successivo dopo che hai letto gli utlimi byte presenti nel file)...
Originally posted by "leon84"
Ah scusa ho capito queste istruzioni commettevo io l'errore . Ma non sarebbe meglio fare così la condizione di uscita ? Così risparmierei un cilco ti trovi ? Quanto alla CreateFile si ho capito , scusami . Poi un'altra cosa , come stanno le cose e siccome l'integer è di 4 byte non posso inviare un file superiore a 32 K ?
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
Loop While read <BYTE_PER_MSG
No perchè anche quando read è < di BYTE_PER_MSG quei byte letti li devi comunque inviare...
Inoltre è utile inviare anche un messaggio di lunghezza zero epr far capire al programma che sta dall'altra parte che il file è finito ;)
Originally posted by "leon84"
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
Loop While read <BYTE_PER_MSG
Così poi non va bene...se il file è di dimensione superiore a BYTE_PER_MSG byte ti uscirebbe al primo ciclo ;)
Se lo vuoi fare così lo devi scrivere in questo modo :
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
Loop Until read <BYTE_PER_MSG
In ogni caso valgono le considerazioni fatte sopra...
Si scusa ho dimenticato la funzione SendMsg read,buffer . Così andrebbe bene ?
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
SendMsg read, buffer
Loop While read < BYTE_PER_MSG
No serve Until al posto di While... Inoltre come ho già detto dovresti inviare anche un messaggio di lunghezza zero per far capire al programma che riceve il file che il file è terminato...
Originally posted by "cionci"
No serve Until al posto di While... Inoltre come ho già detto dovresti inviare anche un messaggio di lunghezza zero per far capire al programma che riceve il file che il file è terminato...
Ah si scusa che stupido , ci vuole Until . Un'altra cosa : ma l'istruzione int(data) a cosa serve ? A convertire da binario a decimale ?
Originally posted by "leon84"
Ah si scusa che stupido , ci vuole Until . Un'altra cosa : ma l'istruzione int(data) a cosa serve ? A convertire da binario a decimale ?
Dire "convertire da binario a decimale" non è esatto...perchè binario e decimale sono due rappresentazioni diverse dello stesso numero...ed in ogni caso qualsiasi numero nel PC è rappresentato solamente in binario...
Serve per covertire dal tipo Byte al tipo Integer....
Si ma implicitamente avviene quella conversione giusto ? Cmq guarda il codice che ho modificato della SendMSg
Private Sub SendMsg(num As Long, buf() As Byte)
Dim tmp(4) As Byte, I As Long
Dim v As Variant
tmp(1) = (num And &HFF000000) / &H1000000
tmp(2) = (num And &HFF0000) / &H10000
tmp(3) = (num And &HFF00) / &H100
tmp(4) = num And &HFF
v = tmp
MSComm1.CommPort = 1
MSComm1.PortOpen = True
MSComm1.Output = v
'Non so se buf vada ridimensionato comunque lo faccio uguale
v = buf
MSComm1.Output = v
MSComm1.PortOpen = False
End Sub
Il ridimensionamento del buffer l'ho eliminato perché mi ha dato problemi . A proposito il ridimensionamento che io sapevo si faceva impostando la proprietà outbuffersize o inbuffersize dell'oggetto Mscomm . Quella istruzione che hai postato è valida lo stesso ? Cmq adesso mi è tutto chiaro . Leggo 16 byte alla volta che posso anche aumentare , ed invio sulla seriale i primi 4 byte che convertiti in integer mi danno 16 e successivamente i 16 byte del file . Fccio questo fino a quando read risulta minore del numero buffer . Ora mi chiedo : nell'evento Oncomm() dell'oggetto MSCOMM una proprietà cambierà a seconda se sono presenti elementi o meno sul buffer . Quando dovrò leggere dal buffer quali operazioni dovrò compiere ? In teoria dovrei leggere il numero 16 in questo caso e leggere i 16 byte e così via , ma in pratica nel buffer questi pacchetti come saranno disposti ?
Ah cionci , mi spieghi nel dettaglio l'operazioni si scomposizione dell'intero in 4 byte differenti ? Ci tengo particolarmente .
Saranno disposti nello stesso ordine in cui li avrai spediti...quindi il più vecchio sarà il primo che legerai dall'altra parte...
Riguardo al 16...ricordati che il numero di byte letti dal file può essere anche minore di 16...
Nella ricezione dei dati continuerai a scrivere nel file i pacchetti letti fino a quando la dimensione dell'ultimo pacchetto letto sarà 0...
Il ReDim lo facevo per il vettore...non ha nulla a che vedere con la dimensione del buffer della seriale...
Originally posted by "leon84"
Ah cionci , mi spieghi nel dettaglio l'operazioni si scomposizione dell'intero in 4 byte differenti ? Ci tengo particolarmente .
L'and bit a bit funziona proprio come dici tu...se io faccio l'and di un intero con una maschera composta da 4 byte tutti a 1 riottengo lo stesso intero senza modifiche...
intero And &HFFFFFFFF quindi è uguale a intero...
&HFFFFFFFF è la rappresentazione esadecimale di un intero...ogni FF è un byte con tutti 1 all'interno... Sai come funziona la rappresentazione in esadecimale (base 16) ?
Quindi se faccio un and con una maschera che ha tutti 1 nell'ultimo bute cosa ottengo ?
intero And &HFFFFFFFF mi rende il byte di valore più significativo all'interno dell'intero però spostato nell'ultima posizione...quindi per ottenere il valore di quel byte dovrò fare uno shift verso destra di quel byte per 3 byte...in modo da portarlo nella posizione del byte meno significativo...
Non sapevo come si faceva lo shift in VB, ma visto che lo shift a destra è equivalente ad una divisione intera per 2 (quello a destra è una moltiplicazione per 2)...allora posso anche dividere per 2 elevato al numero di posizioni di cui spostare... Le posizioni di cui spostare il byte sono 3*8...quindi invece di scrivere il numero corrospondente a 2^24 ho semplicemente rappresentato questo numero in esadecimale e corrisponde ad un 1 nel bit numero 24...quindi &H01000000 ;)
Quello che volevo dire io è che io leggo dal buffer di ricezione con l'istruzione MSCOMM1.input . Il contenuto di questa lettura dove lo riverso ? Che tipo di dato vado a leggere ? Con i messaggi erano delle stringhe e con i byte ?
Non te lo so dire...devi fare delle prove...
Originally posted by "cionci"
Non te lo so dire...devi fare delle prove...
Dove hai trovato la documentazione sul controllo MSCOMM ? Magari li trovo qualcosa
Ho visto che puoi specificare il numero dei byte da leggere !!!
Dim tmp As Byte(4)
MSComm1.InputLen = 4
MSComm.InputMode = comInputModeBinary
tmp = MSComm1.Input
'ora ti devi ricostruire l'intero che andrai a mettere in num (non lo scrivo)
MSComm1.InputLen = num
If MSComm1.InputCounter < num Then
'qui dovresti attendere che arrivino gli altri dati (basta mettere un'attesa ad esempio di 1 decimo di secondo)
'non conviene fare un ciclo perchè ti bloccherebbe facilmente il programma
'In VB non so come si fa al limite ti dico come si usa l'API Sleep...
If MSComm1.InputCounter < num Then 'ora ricontrolliamo di nuovo
'nel caso che ancora non siano sufficienti blocchi il programma e generi un errore
'quindi ora siamo sicuri che ci siano i byte da leggere
buf = MSComm1.Input 'ed hai letto il buffer
'Ora chiami Writefile e scrivi i dati letti nel file...
Originally posted by "leon84"
Dove hai trovato la documentazione sul controllo MSCOMM ? Magari li trovo qualcosa
Su MSDN ;) In pratica sono i CD dell'hep di Visual Studio...
Comunque lo trovi su internet: msdn.microsoft.com e cerchi MSComm
Ma la parte meno significativa non è quella di destra ?
Si uso anch'io MSDN ma non ho trovato queste cose . Magari non ho visto bene
Originally posted by "leon84"
Ma la parte meno significativa non è quella di destra ?
Sì... Ho scritto diversamente ?
Sei semplicemente straordinario . Io credo che in fondo è questa la grande differenza tra l'informatico e l'Ingegnere Informatico . La capacità di documentarsi facilmente e di apprendere con estrema semplicità i diversi linguaggi perché si ha una base molto consistente . Cmq tornando al controllo vedi se ho capito . Hai impostato la modalità di ricezione in binario , la proprietà InputLen indica il numero il numero di byte contenuti nel buffer . Leggo i primi 4 byte che corrispondono al numero di byte presenti nel pacchetto e successivamente leggo i pacchetti . Riverso il tutto nel file . Scusa se ti annoio ma mi risulta un pò difficile la scomposizione dell'intero in 4 byte di cui parlavamo prima . Non è che potresti rispiegarmelo ?
No è cche non mi trovo con questo :
intero And &HFFFFFFFF mi rende il byte di valore più significativo all'interno dell'intero però spostato nell'ultima posizione...quindi per ottenere il valore di quel byte dovrò fare uno shift verso destra di quel byte per 3 byte...in modo da portarlo nella posizione del byte meno significativo...
Non sapevo come si faceva lo shift in VB, ma visto che lo shift a destra è equivalente ad una divisione intera per 2 (quello a destra è una moltiplicazione per 2)...allora posso anche dividere per 2 elevato al numero di posizioni di cui spostare... Le posizioni di cui spostare il byte sono 3*8...quindi invece di scrivere il numero corrospondente a 2^24 ho semplicemente rappresentato questo numero in esadecimale e corrisponde ad un 1 nel bit numero 24...quindi &H01000000
Originally posted by "leon84"
No è cche non mi trovo con questo :
Cioè cosa non ti torna ?
Proviamo a fare l'esempio con un byte solo... Fai che vogliamo ottenere di questo byte i vari valori dele 4 coppie di bit...
Il byte sarà composto da 4 coppie di bit [hg fe dc ba]...
Ovviamente a è il meno significativo...
[hg fe dc ba] And [11 00 00 00] = [hg 00 00 00]
[hg 00 00 00] shift destra di 6 posizioni = [00 00 00 hg]
Al posto dello shift a destra possiamo usare la divisione intera per 2...
[hg 00 00 00] / 2^6 = [00 00 00 hg]
Poi la stessa operazione andrà fatta per ogni coppia di bit...
Si ora mi è chiaro . Grazie cionci . Ora sto provando i vari listati
Ora ti posto tutto il codice completo . Chiaramente non guardare gli eventuali errori non gestiti . Ho fatto in modo che alla fine della lettura del file venga generato un pacchetto di dimensione 0 e numero di byte 0 . In ricezione scrivo fino a quando non mi giunge questo pacchetto : guarda e fammi sapere .
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW = 1
Const CREATE_ALWAYS = 2
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Private Declare Function WriteFile Lib "kernel32" (ByVal hfile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hfile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'La costante sotto la puoi cambiare per aumentare il numero masismo di byte
Const BYTE_PER_MSG = 16
Private Sub SendMsg(num As Long, buf() As Byte)
Dim tmp(4) As Byte, I As Long
Dim v As Variant
tmp(1) = (num And &HFF000000) / &H1000000
tmp(2) = (num And &HFF0000) / &H10000
tmp(3) = (num And &HFF00) / &H100
tmp(4) = num And &HFF
v = tmp
MSComm1.Output = v
'Non so se buf vada ridimensionato comunque lo faccio uguale
v = buf
MSComm1.Output = v
End Sub
Private Sub Command1_Click()
Dim buffer(BYTE_PER_MSG) As Byte, f As Long, read As Long
CommonDialog1.ShowOpen
f = CreateFile(CommonDialog1.FileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
If f = -1 Then
MsgBox "Errore nell'apertura del file !!!"
Else
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
SendMsg read, buffer
Loop Until read < BYTE_PER_MSG
SendMsg 0, buffer
CloseHandle f
End If
End Sub
Private Sub Form_Load()
MSComm1.CommPort = 1
MSComm1.PortOpen = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
MSComm1.PortOpen = False
End Sub
Private Sub MSComm1_OnComm()
If MSComm1.CommEvent = 2 Then
CommonDialog1.ShowSave
Dim hfile As Long
hfile = CreateFile(CommonDialog1.FileName, GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, CREATE_ALWAYS, 0, 0)
Dim tmp(4) As Byte
MSComm1.InputLen = 4
MSComm.InputMode = comInputModeBinary
tmp = MSComm1.Input
Dim num As Long
num = Int(tmp(1)) * &H1000000
num = num + Int(tmp(2)) * &H10000
num = num + Int(tmp(3)) * &H100
num = num + Int(tmp(4))
If num <> 0 Then
MSComm1.InputLen = num
If MSComm1.InputCounter < num Then
Do
While MSComm1.InBufferCount >= num
Dim buf() As Byte
'quindi ora siamo sicuri che ci siano i byte da leggere
buf = MSComm1.Input 'ed hai letto il buffer
WriteFile f, buf(1), num, read, ByVal 0&
Else
CloseHandle f
End If
End If
End Sub
If MSComm1.InputCounter < num Then
Do
While MSComm1.InBufferCount >= num
Avevo sbagliato a scrivere MSComm1.InputCounter, la proprietà giusta è
MSComm1.InBufferCount...
Comunque qui come ti ho già detto non devi fare un'attesa del genere, perchè se ad esempio stacchi il cavo dati mentre il tuo proramma è in funzione sicuramente si pianterà tutto...
Comunque quella situazione gestiscila così :
'Metti in cima la form questo:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
If MSComm1.InBufferCount < num Then
Sleep(200) 'sto fermo per 200 millisecondi
End If
If MSComm1.InBufferCount < num Then
'generi un errore ed esci dalla Sub
ok per il resto è a posto ? Chiaramente lo provo domani a scuola perché il cavo seriale incrociato lo abbiamo fatto li .
Originally posted by "cionci"
Cioè cosa non ti torna ?
Proviamo a fare l'esempio con un byte solo... Fai che vogliamo ottenere di questo byte i vari valori dele 4 coppie di bit...
Il byte sarà composto da 4 coppie di bit [hg fe dc ba]...
Ovviamente a è il meno significativo...
[hg fe dc ba] And [11 00 00 00] = [hg 00 00 00]
[hg 00 00 00] shift destra di 6 posizioni = [00 00 00 hg]
Al posto dello shift a destra possiamo usare la divisione intera per 2...
[hg 00 00 00] / 2^6 = [00 00 00 hg]
Poi la stessa operazione andrà fatta per ogni coppia di bit...
Scusa questo esempio me lo puoi fare per tutte e quattro le coppie di bit ? E che sembra una cosa cretina ed invece mi confondo nello shift . La prima volta shifto di 6 poi di un numero inferiore ? Se mi continui l'esempio forse è meglio
Cioè voglio dire perché shiftare ?
Originally posted by "leon84"
Scusa questo esempio me lo puoi fare per tutte e quattro le coppie di bit ? E che sembra una cosa cretina ed invece mi confondo nello shift . La prima volta shifto di 6 poi di un numero inferiore ? Se mi continui l'esempio forse è meglio
[hg fe dc ba] And [11 00 00 00] = [hg 00 00 00]
[hg 00 00 00] shift destra di 6 posizioni = [00 00 00 hg]
Al posto dello shift a destra possiamo usare la divisione intera per 2...
[hg 00 00 00] / 2^6 = [00 00 00 hg]
[hg fe dc ba] And [00 11 00 00] = [00 fe 00 00]
[00 fe 00 00] shift destra di 4 posizioni = [00 00 00 fe]
Al posto dello shift a destra possiamo usare la divisione intera per 2...
[00 fe 00 00] / 2^5 = [00 00 00 fe]
[hg fe dc ba] And [00 00 11 00] = [00 00 dc 00]
[00 00 dc 00] shift destra di 2posizioni = [00 00 00 dc]
Al posto dello shift a destra possiamo usare la divisione intera per 2...
[00 00 dc 00] / 2^5 = [00 00 00 dc]
[hg fe dc ba] And [00 00 00 11] = [00 00 00 ba]
Ed ora non dobbiamo fare alcuno shift...
Originally posted by "leon84"
Cioè voglio dire perché shiftare ?
Ti faccio il caso in cui vogliamo sapere il valore dei 2 bit più significativi:
Il numero 134 è in binario 128+4+2...cioè 01 00 01 10...
Faccio l'and con 11 00 00 00 ed ottengo 01 00 00 00 che in decimale è 128 ma a me interessa avere il valore della cifra rappresentata da quei due bit (nel caso del messaggio il valore dell'ultimo byte) e per ottenerlo posso shiftare a destra di 6 bit ed ottengo che i due bit più significativi valgono 1 (per la rpecisione 01)...
Si ora è veramente chiaro . Toglimi una curiosità : le funzioni ReadFile,WriteFile sono tipizzate e ritornano tutte un valore Long . Come mai per esempio il valore long non viene utilizzato nel codice ad eccezione della CreateFile . Mi è capitato spesso in C++ di realizzare funzioni tipizzate . Il loro valore doveva per forza essere contenuto in una variaible . Non potevo cioè riciamarle come delle funzioni atipizzate (void) . Perché in VB questo è possibile ?
Originally posted by "leon84"
Il loro valore doveva per forza essere contenuto in una variaible . Non potevo cioè riciamarle come delle funzioni atipizzate (void) . Perché in VB questo è possibile ?
Nono in C e C++ si può tranquillamente fare ;)
int f(int a)
{
....
}
Si può tranquillamente richiamare:
f(a);
senza usarne il risultato...
veramente ? lo sai che non lo sapevo ?
Nella chat che sto realizzando scambio messaggi di testo senza alcun problema : ora voglio inserire un menù che chiamo "Invia file" . Quando ci clicco si apre la finestra di dialogo che mi fa selezionare il file da inviare . Io lo seleziono e con tutte quelle procedure invio e ricevo il file . Il problema è : Come faccio a far capire all'altra applicazione che i dati che gli giungeranno sono i byte del file e non messaggi di testo ? Avevo pensato ad un identificatore per esempio "-99999999" . Quando riceve questo messaggio attiva la procedura di ricezione del file . Che ne pensi ?
Fai così...il numero di byte del messaggio invece di metterlo su un Long lo metti su un Integer (16 bit)...
Se lo metti a 16 bit devi togliere le due conversioni per i byte più alti...
tmp fallo di 3 invece di 4 e sul primo Byte ci metti un byte di controllo...
SendMsg diventerà così:
Private Sub SendMsg(cmd As Byte, num As Integer, buf() As Byte)
Dim tmp(3) As Byte
Dim v As Variant
tmp(1) = cmd
tmp(2) = (num And &HFF00) / &H100
tmp(3) = num And &HFF
Ti devi definire diverse costanti all'interno del programma:
Const FILE_NAME &H04
Indica che ilpacchetto contiene un nome di un file (ad esempio per trasferire un file dall'altra parte e dargli lo stesso nome che dalla parte di chi lo manda)
Const FILE_DATA &H02
Indica che il pacchetto contiene i dati di un file
Const TEXT_DATA &H01
Indica che il pacchetto contiene i dati di un messaggio di testo
Const END_OF_DATA &H08
Questo può servire sia per indicare la fine di un nome di file, dei dati di un file e di un messaggio di testo
Const END_OF_CONNECTION &H80
Questo ti può servire per fare la disconnessione...magari l'altro PC dovrà risponderti con un altro apcchetto di END_OF_CONNECTION
Ad esempio l'invio del file diventerà così :
Do
ReadFile f, buffer(1), BYTE_PER_MSG, read, ByVal 0&
'Ora richiamo la Sub che invia i dati
If read < BYTE_PER_MSG Then
SendMsg read, buffer, FILE_DATA Or END_OF_DATA
Else
SendMsg read, buffer, FILE_DATA
End If
Loop Until read < BYTE_PER_MSG
CloseHandle f
Durante la ricezione...per testare se hai un tipo o un altro di dati basta fare :
If (tmp(1) And FILE_NAME) > 0 Then
...
ElseIf (tmp(1) And TEXT_DATA) > 0 Then
...
End If
'Per testare l'END_OF_DATA usi lo stesso metodo
Ora faccio una cosa . Siccome ho creato un progetto a parte per il solo invio del file , domani a scuola lo provo . Se funziona e non mi dà alcun problema allora passo alla parte riguardante quelle costanti . Ah ... una cosa .... ma quelle costanti li definisco io o già esistono ?
Nono...le definisci te...
E' importante che ognuna rappresenti un bit del byte cmd...
Ah...aspetta...in SendMsg ho messo in cima cmd, mentre quando l'ho usato l'ho messo in fondo...
Si me ne sono accorto ma non ti preoccupare
Insomma, in poche parole ampliando il numero di byte per cmd puoi farci qualsiasi cosa... Come ad esempio controllare un PC in remoto...ricevere la lista delle directory...la lista dei file nelle directory...cambiare directory remota e qualsiasi altra cosa che ti viene in mente ;)
Originally posted by "cionci"
Insomma, in poche parole ampliando il numero di byte per cmd puoi farci qualsiasi cosa... Come ad esempio controllare un PC in remoto...ricevere la lista delle directory...la lista dei file nelle directory...cambiare directory remota e qualsiasi altra cosa che ti viene in mente ;)
veramente ? in che senso scusa ? Mettiamo che voglio conoscere il contenuto dell'hard disk del computer a cui mi connetto . Come faccio ?
Andiamo per gradi...
Metti che cmd sia un integer e non un byte...
Puoi definire altre costanti (fino a 16)...
Ad esempio puoi definire altre costanti DIR_LIST_QUERY, DIR_LIST_RESPONSE e un altra che genera una condizione di errore (significa che il ricevente non può eseguire il comando inviato) che chiamo CMD_ERROR...
SendMsg 9, "C:\CICCIO", DIR_LIST_QUERY Or END_OF_DATA
Mettiamo che nel disco C: ci siano 3 directory: PIPPO, PLUTO, TOPOLINO.
Il ricevente con un ciclo risponderà con una serie di messaggi contenti le varie directory:
SendMsg 5, "Pippo", DIR_LIST_RESPONSE
SendMsg 5, "Pluto", DIR_LIST_RESPONSE
SendMsg 8, "Topolino", DIR_LIST_RESPONSE Or END_OF_DATA
Poi se definisci anche FILE_LIST_QUERY e FILE_LIST_RESPONSE:
SendMsg 9, "C:\CICCIO", DIR_LIST_QUERY Or END_OF_DATA
Ed ovviamente il ricevente risponderà con i file contenuti nella directory Ciccio...
Poi chi più ne ha più ne metta... Cancellare i file...copiarli in un'altra posizione...rinominarli (si può usare anche la copia non c'è bisogno di ridefinire altre costanti)...
Originally posted by "cionci"
Andiamo per gradi...
Metti che cmd sia un integer e non un byte...
Puoi definire altre costanti (fino a 16)...
Ad esempio puoi definire altre costanti DIR_LIST_QUERY, DIR_LIST_RESPONSE e un altra che genera una condizione di errore (significa che il ricevente non può eseguire il comando inviato) che chiamo CMD_ERROR...
SendMsg 9, "C:\CICCIO", DIR_LIST_QUERY Or END_OF_DATA
Mettiamo che nel disco C: ci siano 3 directory: PIPPO, PLUTO, TOPOLINO.
Il ricevente con un ciclo risponderà con una serie di messaggi contenti le varie directory:
SendMsg 5, "Pippo", DIR_LIST_RESPONSE
SendMsg 5, "Pluto", DIR_LIST_RESPONSE
SendMsg 8, "Topolino", DIR_LIST_RESPONSE Or END_OF_DATA
Scusa non ti seguo . Abbiamo detto che cmd è un byte di controllo . Ora fammi capire DIR_LIST_QUERY e le altre sono costanti che devo sempre dichiarare a mio piacere ? Poi un'altra cosa : cosa significa quando alla funzione SendMSg invii come parametro DIR_LIST_RESPONSE Or END_OF_DATA . Cioè voglio capire quell'or che funzione ha ?
Cmd lo puoi ampliare a tuo piacere....e a tuo piacere puoi definire anche quelle costanti...
END_OF_DATA abbiamo detto che significa che il messaggio corrente è l'ultimo della serie... Mettere un Or significa che quando fai il test con l'And per verificare se una costante è settata (in qualche messaggio sopra ti avevo detto che per fare i test per vedere se una costante è settata bisogna fare un OR, ma avevo sbagliot a scrivere...ci vuole l'And) ti rende un numero > zero (questo perchè abbiamo detto che ogni costante è un bit distinto di cmd)...
Nota che questo è il metodo che usano praticamente tutte le funzioni delle API di Windows... Ad esempio in CreateFile se volevi che il file aperto potesse essere sia letto che scritto da altri mentre è aperto da te basta mettere FILE_SHARE_WRITE Or FILE_SHARE_READ...
Oppure se vuoi aprire un file sia in lettura che in scrittura basta combinare le due opzioni GENERIC_READ e GENERIC_WRITE con l'Or...
In pratica usando l'Or setti a 1 il bit di cmd corrispondente alla costante usata...
Inizio a non capirci più . Forse perché ho passato tutto il giorno a capire il resto .
Allora stamattina ho provato ma sfortunatamente ecco presentarsi i problemi . Quando dichiaro la matrice tmp(4) , dopo mi impedisce di fare :
MSCOMM1.output = tmp . Ed anche quando leggo , facendo tmp = MSCOMM1.input mi da problemi . Come si può ovviare ?
Come avevo fatto io...devi assegnare tmp ad un variant...e poi il variant alla output...
Stessa cosa per la input...
Originally posted by "cionci"
Come avevo fatto io...devi assegnare tmp ad un variant...e poi il variant alla output...
Stessa cosa per la input...
Allora : per quanto riguarda l'output ok lo assgno al variant . Ma quando leggo come faccio ? Leggo in un variant ? e poi ? come faccio ad assegnare a tmp(1) il primo byte a tmp(2) il secondo e così via ?
Sinceramente non lo so, prova ad assegnare il variant a tmp...
Semplicemente tmp = v...
Originally posted by "cionci"
Sinceramente non lo so, prova ad assegnare il variant a tmp...
Semplicemente tmp = v...
Ho già provato . Era questo infatti il problema . All'invio il problema non c'è . Il problema nasce dopo . Come potrei ovviare ? Ci sto perdendo la testa ....
Prova ad indicizzare direttamente il variant...
v(1), v(2)...
Non credo funzioni perché ho anche provato a ricevere un solo byte in un variant però quando lo riverso nel tmp lo stesso non va . Ci provo lo stesso e ti faccio sapere
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.