Trong bài này, mình sẽ hướng dẫn các bạn sử dụng UDP client và UDP server thông qua các api của lwip
Có 3 cách cơ bản để sử dụng lwip
- RAW / API gốc – một giao diện được sử dụng mà không cần hệ điều hành. Nó có một số nhược điểm, nhưng cũng có một số ưu điểm, chẳng hạn như cung cấp quyền tự do hành động, điều thường thiếu ở các api cao cấp hơn
- Netconn API là API nối tiếp cấp cao yêu cầu hệ điều hành thời gian thực (RTOS). Netconn API cho phép hoạt động đa luồng.
- BSD Socket API – Một API tương tự như Berkeley-Socket (được phát triển dựa trên API của Netconn)
Bây giờ chúng ta sẽ làm việc với giao diện RAW để gửi nhận udp server nhé
Các bạn tạo 2 file tên là row_api_udp_server.h và row_api_udp_server.c Có thể lưu nó trong Inc và Src. Sau đó add source file vào cây thư mục của project
Copy các hàm mình đã viết vào thư viện row_api_udp_server.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include "row_api_udp_server.h" uint16_t UDP_SERVER_PORT; uint16_t UDP_CLIENT_PORT; void udp_server_init(uint16_t serverPort,uint16_t clientPort) { UDP_SERVER_PORT=serverPort; UDP_CLIENT_PORT=clientPort; struct udp_pcb *upcb; err_t err; /* Create a new UDP control block */ upcb = udp_new(); if (upcb) { /* Bind the upcb to the UDP_PORT port */ /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT); if(err == ERR_OK) { /* Set a receive callback for the upcb */ udp_recv(upcb, udp_server_receive_callback, NULL); } } } void udp_server_echo(struct udp_pcb *upcb,uint8_t *dat,uint16_t len) { struct pbuf *p; p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_POOL); if (p != NULL) { pbuf_take(p, (void *) dat, len); udp_send(upcb, p); pbuf_free(p); } } void udp_server_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { /* Connect to the remote client */ udp_connect(upcb, addr, UDP_CLIENT_PORT); udp_send(upcb, p);//server echo //------------ //uint8_t * dat = (uint8_t *)(p->payload); //get data, data len = p->len //udp_server_echo(upcb,(uint8_t *)"OK\r\n",4); //server reply custom data //------------ /* free the UDP connection, so we can accept new clients */ udp_disconnect(upcb); /* Free the p buffer */ pbuf_free(p); } |
Code cho row_api_udp_server.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#ifndef ROW_API_UDP_SERVER__ #define ROW_API_UDP_SERVER__ //----------------------------------------------- #include "main.h" #include <string.h> #include <stdlib.h> #include <stdint.h> #include "lwip_user.h" #include "lwip/udp.h" #include "lwip/pbuf.h" //----------------------------------------------- void udp_server_init(uint16_t serverPort,uint16_t clientPort); void udp_server_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); //----------------------------------------------- #endif /* ROW_API_UDP_CLIENT__ */ |
Trong file main.c add thêm thư viện udp server
Mình sẽ khởi chạy dịch vụ udp server ở port 1000 sau khi Ethernet khởi tạo thành công và có IP
Các bạn hãy để ý trong hàm udp_server_receive_callback trong file row_api_udp_server.c đây là nơi chúng ta sẽ nhận dữ liệu. Ở đây mình đã cho server echo mọi data nó nhận được bằng lệnh udp_send(upcb, p);
Nếu các bạn muốn nhận data và xử lí thì hãy xóa lệnh đó và lấy data thông qua con trỏ p->playload và độ dài data thông qua p->len
OK ! Bây giờ nạp chương trình và mở Hercules lên để test thử nhé. Mình sẽ vào tab UDP và kết nối tới server thông qua cổng 1000
UDP Client
Tiếp tục tạo 2 file tên là row_api_udp_client.h và row_api_udp_client.c Có thể lưu nó trong Inc và Src. Sau đó add source file vào cây thư mục của project
Copy các hàm mình đã viết vào thư viện row_api_udp_client.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include "row_api_udp_client.h" //----------------------------------------------- struct udp_pcb *upcb; char str1[30]; //----------------------------------------------- void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); //----------------------------------------------- void udp_client_connect(void) { ip_addr_t DestIPaddr; err_t err; upcb = udp_new(); if (upcb!=NULL) { IP4_ADDR(&DestIPaddr, 192, 168, 1, 7); upcb->local_port = 1000; err= udp_connect(upcb, &DestIPaddr, 1000); if (err == ERR_OK) { udp_recv(upcb, udp_receive_callback, NULL); } } } //----------------------------------------------- void udp_client_send(uint8_t *dat) { struct pbuf *p; uint16_t len = strlen((char *)dat); p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_POOL); if (p != NULL) { pbuf_take(p, (void *) dat, len); udp_send(upcb, p); pbuf_free(p); } } //----------------------------------------------- void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { //memcpy((char *)&bmp_frame[rv],p->payload,p->len); //copy data ra de xu li neu muon pbuf_free(p); } //-------------------------------------------------- |
Trong hàm connect, mình đang để mặc định sẽ kết nối tới udp server máy tính của mình, tức 192.168.1.7:1000, các bạn hãy thay thế nó thành ip máy tính của bạn hoặc custon lại phần này để truyền ip muốn connect vào nhé
Copy các hàm mình đã viết vào thư viện row_api_udp_client.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#ifndef ROW_API_UDP_CLIENT__ #define ROW_API_UDP_CLIENT__ //----------------------------------------------- #include "main.h" #include <string.h> #include <stdlib.h> #include <stdint.h> #include "lwip_user.h" #include "lwip/udp.h" //----------------------------------------------- void udp_client_connect(void); void udp_client_send(uint8_t *dat); //----------------------------------------------- #endif /* ROW_API_UDP_CLIENT__ */ |
Add thư viện vào file
Khởi chạy udp client và gửi data lên pc sau mỗi 1s
Các bạn có thể tải source cho bài này tại đây