Introduzione
Avvertenze per l'uso corretto della comunicazione UDP da applicazioni R3:
•La comunicazione UDP su ethernet effettuata da applicativo R3 funziona esclusivamente utilizzando l'interfaccia ethernet presente a bordo della scheda CPU. Non può essere utilizzata per comunicare tramite un'interfaccia ethernet presente su altre schede (es. scheda Netint)
•Per sue caratteristiche intrinseche, la comunicazione UDP non garantisce la consegna dei pacchetti di dati. L'applicazione deve farsi carico, se richiesto, della verifica e della ritrasmissione dei pacchetti persi
•La comunicazione UDP non garantisce la tempistica di trasmissione
•La comunicazione UDP non garantisce la sequenza temporale di ricezione dei pacchetti. Il pacchetto P2, trasmesso dopo il pacchetto P1, può essere ricevuto prima di P1. L'applicazione deve farsi carico, se richiesto, del riordino dei dati
•L'handle associato a una comunicazione UDP (valore restituito dalle funzioni udp_open_) ha senso unicamente nell'ambito del task R3 in cui è stata effettuata la open. Non è possibile utilizzare l'handle in un task differente per eseguire chiamate ad altre funzioni UDP
•È possibile trasmettere con una singola chiamata di una funzione udp_ fino ad un massimo di 65535 byte. Nel S.O. (livello IP) la trasmissione avviene con spezzettamento del buffer in blocchi di dimensione massima pari a MAX_UDP_DATA = 508. Se uno di questi pacchetti fallisce la trasmissione, tutto il buffer, di conseguenza, viene perso
•Le funzioni udp_send_notify() e udp_recv_notify() devono in ogni caso avere un buffer limitato a MAX_UDP_DATA byte
•L'utente che realizza da task R3 una applicazione server UDP può utilizzare il numero di porta che desidera per la connessione. Si consiglia comunque di evitare la fascia da 8000 a 8999, per evitare conflitti con le attuali e future implementazioni Robox
Istruzioni
udp_close() |
Chiusura di una comunicazione UDP |
udp_open_client() |
Apertura di una comunicazione UDP di tipo client |
udp_open_server() |
Apertura di una comunicazione UDP di tipo server |
udp_recv() |
Ricezione di un messaggio UDP da una stazione precedentemente specificata |
udp_recv_from() |
Ricezione di un messaggio UDP da una stazione specificata |
udp_recv_notify() |
Ricezione di un messaggio UDP (notifica) da una stazione precedentemente specificata |
udp_send() |
Invio di un messaggio UDP a una stazione precedentemente specificata |
udp_send_notify() |
Invio di un messaggio UDP con notifica a una stazione precedentemente specificata |
udp_send_to() |
Invio di un messaggio UDP a una stazione specificata |
ipaddr_to_str() |
Supporto |
str_to_ipaddr() |
Supporto |
NOTA: Un esempio client/server è presente in RDE3-->workspace-->esempi predefiniti.
Esempio
$task 1 ;==================================================================== ; Esempio di client UDP per scambio messaggi con notifica. ; Richiede al server il valore di 50 registri rr, a partire da rr(30) ; Copia i dati della risposta nei registri a partire da rr(150). ;==================================================================== ; Struttura per invio comando lit size_buffer 16 STRUCT_P buff_send U32 msgId I32 comando I32 reg_start I32 reg_num end_struct_p buff_send buffer ; struttura per ricezione dati lit size_bufrec 812 STRUCT_P buff_recv I32 msgId I32 comando I32 reg_num REAL regs[100] end_struct_p buff_recv bufrec U32 ip_srvaddr = 0x0a001011; ; indirizzo del server = 10.0.16.17 U32 udp_srvport = 18000 ; il server è su porta 18000 I32 codOpen, codSend, codRecv I32 i ; Inizio task ; Apertura comunicazione codOpen = udp_open_client(udp_srvport, ip_srvaddr ) if (codOpen < 0) alarm s, "err. udp_open (client)" while (1) dwell(1) end_while endif loop: ; trasmissione comando buffer.comando = 2 ; display rr() buffer.reg_start = 50 ; da rr(50) buffer.reg_num = 30 ; 30 rr() codSend = udp_send_notify(codOpen, buffer, size_buffer) if (codSend < 0) alarm s, "1002 error send_notify (client)" dwell(1) goto loop endif ; ricezione while (1) codRecv = udp_recv_notify(codOpen, bufrec, size_bufrec, 0.2, 2) if (codRecv = 0) ; la risposta non è ancora arrivata dwell (0.01) continue endif if (codRecv < 0) ; ricezione con errore alarm s, "1003 error recv_notify (client)" dwell (1) goto loop endif ; messaggio ricevuto OK... for (i=0, i<buffer.reg_num, i=i+1) ; copiatura dei dati rr(100+buffer.reg_start+i) = bufrec.regs[i] end_for break end_while dwell (0.05) goto loop $task 2 ;==================================================================== ; Esempio di server UDP per scambio messaggi con notifica ; Riceve un comando dal client (richiesta di registri reali). ; Esegue il comando spedendo al client il valore di 30 registri RR ; a partire da RR(50). ;==================================================================== ; struttura per ricezione comando lit size_buf_from 16 STRUCT_P buff_send U32 msgId I32 comando I32 reg_start I32 reg_num end_struct_p buff_send buf_from ; struttura per invio risposta lit size_buf_to 812 STRUCT_P buff_recv U32 msgId I32 comando I32 reg_num REAL regs[100] end_struct_p buff_recv buf_to I32 udp_remport = 18000 ; porta del server I32 ip_remaddr I32 codOpenS, codSendS, codRecvS I32 i ; Inizio Task ; apertura da tutte le interfacce eth. locali (nessun indirizzo specificato) codOpenS = udp_open_server(udp_remport) if (codOpenS < 0) alarm s, "err. udp_open (server)" endif loop: ; ricezione messaggi codRecvS = udp_recv_from(codOpenS, buf_from, size_buf_from, udp_remport, ip_remaddr ) if (codRecvS = 0) goto loop endif if (codRecvS < 0) ; ricezione con errore alarm s, "err. udp_recv_from (server)" dwell(1) goto loop endif ; preparazione risposta buf_to.msgId = buf_from.msgId buf_to.comando = buf_from.comando buf_to.reg_num = buf_from.reg_num for (i=0, i<buf_from.reg_num, i=i+1) buf_to.regs[i] = rr(buf_from.reg_start+i) end_for
; invio risposta codSendS = udp_send_to(codOpenS, buf_to, size_buf_to, udp_remport, ip_remaddr) if (codSendS < 0) ; spedizione con errore alarm s, "1001 error send_to (server)" dwell (1) goto loop endif goto loop |