Sending and receiving UDP using the same port does not work with the asio library? - udp

I'm trying to send and receive UDP packets through the same endpoint. As far as I know this should be possible. But I can not get it to work with the asio library (version 1.20.0).
This is what I do:
asio::io_context io_context;
asio::ip::udp::socket* udpSendRecvSocket = new asio::ip::udp::socket(io_context, asio::ip::udp::endpoint(asio::ip::udp::v4(), 7782));
asio::error_code ec;
char data[1000];
//
// send packet
//
std::string ipAddress = "127.0.0.1";
asio::ip::address ip_address = asio::ip::address::from_string(ipAddress);
asio::ip::udp::endpoint remoteTarget_endpoint(ip_address, 5500);
udpSendRecvSocket->send_to(asio::buffer(data, 50), remoteTarget_endpoint, 0, ec);
if (ec) {
return 0;
}
//
// receive packets
//
size_t avLen = udpSendRecvSocket->available(ec);
while (avLen) {
asio::ip::udp::endpoint remote_endpoint;
size_t length = udpSendRecvSocket->receive_from(asio::buffer(data, 1000), remote_endpoint, 0, ec);
int p = remote_endpoint.port();
if (ec) {
return 0;
}
avLen -= length;
}
The receive does not work correctly. I do receive a packet that I send (from some other app). I know because avLen gets the right value. But when executing the receive_from(), if fails. And the port number in p gets the value 5500. This is the value of the target port of the send_to() call that was executed before.
The strange thing is that when I remove the send_to() call, the receive does work correctly and the p will reflect the correct port number of the sending application.
Is this a bug?

Related

Sending message from udp client to udp server without sending protocol address of client

I have a query is it possible to send data from udp client to udp server without sending the protocol address and then from server to client
Server.c
if(bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
printf("Couldn't bind to the port\n");
return -1;
}
printf("Done with binding\n");
printf("Listening for incoming messages...\n\n");
// Receive client's message:
if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,
(struct sockaddr*)NULL, NULL) < 0){
printf("Couldn't receive\n");
return -1;
}
// printf("Received message from IP: %s and port: %i\n",
// inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
printf("Msg from client: %s\n", client_message);
// Respond to client:
int n = atoi(client_message);
int m =0, sum = 0;
while(n>0){
m=n%10;
sum=sum+m;
n=n/10;
}
sprintf(server_message, "%d", sum);
if (sendto(socket_desc, server_message, strlen(server_message), 0,
(struct sockaddr*)&client_addr, client_struct_length) < 0){
printf("Can't send\n");
return -1;
}
When I send data from client to server the server printed what I had sent from client but then then when I tried to send data back to client it is unable to send the modified data.
client_addr does not magically get filled with the clients address. It has to be explicitly done in recvfrom - but you use instead NULL there and thus throw away this information:
if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,
(struct sockaddr*)NULL, NULL) < 0){

How to receive data over Ethernet using LWIP, UDP

I'm trying to send data to and from my computer and an STM32H745 over Ethernet using LwIP and UDP. I have successfully configured the card and right now I can send data from the card to a Python script running on the computer. However, I don't understand how udp_recv works <udp,lwip> or how to receive data with UDP on LwIP in general, and I can't find examples that do just that. Where is the data being received? Should I even use udp_recv?
In the main loop I run MX_LWIP_Process, which runs ethernetif_input which somehow handles the received data, but I don't understand where it puts it.
Below is the main code, just for reference.
const char* message = "a";
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1); // orange
ip_addr_t PC_IPADDR;
IP_ADDR4(&PC_IPADDR, 192, 168, 1, 200);
u16_t port = 8000;
struct udp_pcb* my_udp = udp_new();
struct pbuf* udp_buffer = NULL;
/* Infinite loop */
for (;; )
{
MX_LWIP_Process();
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1); // orange
HAL_Delay(1000);
udp_buffer = pbuf_alloc(PBUF_TRANSPORT, strlen(message), PBUF_RAM);
if (udp_buffer != NULL)
{
memcpy(udp_buffer->payload, message, strlen(message));
udp_sendto(my_udp, udp_buffer,&PC_IPADDR, port);
pbuf_free(udp_buffer);
}
//udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
}
udp_recv() does not actually receive UDP datagrams (despite its name). It registers a callback function that will then be called by MX_LWIP_Process() when a datagram has been buffered. It would better be called udp_set_recv_callback(), but it is what it is.
To that end you should call it once before your executive loop:
udp_bind( my_udp, IP_ADDR_ANY, port ) ;
udp_recv( my_udp, udp_receive_callback, NULL ) ;
/* Infinite loop */
for (;; )
{
// Run the CubeMX LwIP stack
MX_LWIP_Process() ;
...
}
Where udp_receive_callback is a function that will be invoked on receipt of a datagram:
void udp_receive_callback( void* arg, // User argument - udp_recv `arg` parameter
struct udp_pcb* upcb, // Receiving Protocol Control Block
struct pbuf* p, // Pointer to Datagram
const ip_addr_t* addr, // Address of sender
u16_t port ) // Sender port
{
// Process datagram here (non-blocking code)
...
// Must free receive pbuf before return
pbuf_free(p);
}
Examples include:
https://gist.github.com/iwanbk/1399729
https://github.com/STMicroelectronics/STM32CubeF2/blob/master/Projects/STM322xG_EVAL/Applications/LwIP/LwIP_UDP_Echo_Client/Src/udp_echoclient.c
Documentation can be found at https://www.nongnu.org/lwip/2_0_x/group__udp__raw.html

Mina transmission frequency is too fast, causing received packets are merged

I'm using Apache Mina framework for communication between server and client, when I test the programe, I found if my transmission frequency is too fast, the received packets will merge to a big one, which should be each separate package.
My client used to send message, code like below:
public static void main(String[] args) {
// IoConnector instance
IoConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(3000); // 连接超时时间
// configure filters
// connector.getFilterChain().addLast("coderc", new ProtocolCodecFilter(
// new TextLineCodecFactory(Charset.forName("UTF-8"))));
DefaultIoFilterChainBuilder builder = (DefaultIoFilterChainBuilder) connector.getFilterChainBuilder();
Map<String, IoFilter> filters = new LinkedHashMap<>();
filters.put("protocolCodecFilter", new ProtocolCodecFilter(new TcpCodecFactory()));
filters.put("executor", new ExecutorFilter());
filters.put("loggingFilter", new LoggingFilter());
builder.setFilters(filters);
connector.setFilterChainBuilder(builder);
// set handler
connector.setHandler(new TcpServerHandler());
// connect to the server
ConnectFuture future = connector.connect(new InetSocketAddress(address, port));
future.awaitUninterruptibly(); // waiting for connection
IoSession session = future.getSession();
byte[] data = new byte[10];
for (int i = 0; i < 100; ++i) {
data[0] = (byte)i; // first byte means the message sequence number
for (int j = 1; j < 10; ++j) {
data[j] = (byte) (j + 10);
}
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
session.write(data);
}
session.getCloseFuture().awaitUninterruptibly(); // wait for close
connector.dispose();
}
When I comment the sleep code, which means I send message frequently, My received message will like below:
The message sequence number is 0, 1, 6..., If I uncomment the sleep code, the message sequence number is 0, 1, 2, 3...
What's the difference? How to avoid the mixed packets in fast transmission?
You are using a TCP socket which is a stream channel versus UDP which is a message channel. Your messages are being combined because that is how TCP works on all platforms to effectively create as few network packets as possible.
Unless the messages are out of order, then this is the expected behavior.

Receiving data from a server using ESP8266 /Arduino Uno

I have a Raspberry Pi working as a WiFi hotspot and an Arduino Uno trying to get data from it using an ESP8266 module.
This is my receiver code for Arduino:
#include <SoftwareSerial.h>
#include <SerialESP8266wifi.h>
#define sw_serial_rx_pin 4 // Connect this pin to TX on the esp8266
#define sw_serial_tx_pin 6 // Connect this pin to RX on the esp8266
#define esp8266_reset_pin 5 // Connect this pin to CH_PD on the esp8266, not reset. (let reset be unconnected)
SoftwareSerial swSerial(sw_serial_rx_pin, sw_serial_tx_pin);
// the last parameter sets the local echo option for the ESP8266 module..
SerialESP8266wifi wifi(swSerial, swSerial, esp8266_reset_pin, Serial);//adding Serial enabled local echo and wifi debug
String inputString;
boolean stringComplete = false;
unsigned long nextPing = 0;
void setup() {
inputString.reserve(20);
swSerial.begin(9600);
Serial.begin(9600);
while (!Serial)
;
Serial.println("Starting wifi");
wifi.setTransportToTCP();// this is also default
// wifi.setTransportToUDP();//Will use UDP when connecting to server, default is TCP
wifi.endSendWithNewline(true); // Will end all transmissions with a newline and carriage return ie println.. default is true
wifi.begin();
wifi.connectToAP("RPi", "raspberry");
wifi.connectToServer("192.168.50.1", "1234");
wifi.send(SERVER, "ESP8266 test app started");
}
void loop() {
//Make sure the esp8266 is started..
if (!wifi.isStarted())
wifi.begin();
//Send what you typed in the arduino console to the server
static char buf[20];
if (stringComplete) {
inputString.toCharArray(buf, sizeof buf);
wifi.send(SERVER, buf);
inputString = "";
stringComplete = false;
}
//Send a ping once in a while..
if (millis() > nextPing) {
wifi.send(SERVER, "Ping ping..");
nextPing = millis() + 10000;
}
//Listen for incoming messages and echo back, will wait until a message is received, or max 6000ms..
WifiMessage in = wifi.listenForIncomingMessage(6000);
if (in.hasData) {
if (in.channel == SERVER)
Serial.println("Message from the server:");
else
Serial.println("Message a local client:");
Serial.println(in.message);
//Echo back;
wifi.send(in.channel, "Echo:", false);
wifi.send(in.channel, in.message);
nextPing = millis() + 10000;
}
//If you want do disconnect from the server use:
// wifi.disconnectFromServer();
}
//Listen for serial input from the console
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
When I execute, the serial monitor shows:
OK ARFa C⸮C⸮j⸮H⸮AT+AWJAP="RPi",#raspberry" WIFI DISCONNECT WIFI
CONNECVED WIFI GOT IP
OK AT+CIFSR
+CIFSR:STAIP,"192.168.50.13"
+CIFQR:STAMAC,"2c:3a:eAT+CIPSTART=4,"TCP","192.0n8.50.1",121l
Link type ERROR
Raspberry Pi's ISC DHCP server:
wlan0: STA 2c:3a:e8:4e:bf:70 RADIUS: starting accounting session
5A3B2C85-000000E9 wlan0: STA 2c:3a:e8:4e:bf:70 WPA: pairwise key
handshake completed (RSN)
I also referred to this SO thread with no luck.
Some assumptions because you have not given the info:
Arduino IDE >=1.85
ESP8266 Community package >=2.41
ESP Module ESP8266-12E with latest AT firmware
if that is the case and these fragments (enclosed by X X) are no typos
+CIFQR:STAMAC,"2c:3a:eXAT+CIPSTART=4,"TCP","192.0XnX8.50.1",121l
this leaves the following points to check
hardware connectors - serial connectors between arduino and esp module
stable power source 3.3V for the ESP module
Sure this is ok - but just in case and as reference for other readers
serial speed - try to increase from 9600 to 57600 or even to 115200 baud
These pieces of code should be in the setup() and not in the loop()
//Make sure the esp8266 is started..
if (!wifi.isStarted())
wifi.begin();
//Send what you typed in the arduino console to the server
static char buf[20];
Code processing
nextPing = millis() + 10000;
at the end of
if (in.hasData) {
might lead to interuptions in the communication
Reason due to the processing of code this might trigger at an unwanted point

SMBus (I2C) sending extra ACK then intended

I'm trying to get a basic handshake going. Below is the ISR for the C8051F120's SMBus (System Management Bus). I'm trying to implement an I2C device on it (ads1115 7addr 0x48 for those who are curious). Note this is mainly the example given by silicon labs for the F120.
void SMBUS_ISR (void) interrupt 7
{
bit FAIL = 0; // Used by the ISR to flag failed
// transfers
static unsigned char sent_byte_counter;
static unsigned char rec_byte_counter;
// Status code for the SMBus (SMB0STA register)
switch (SMB0STA)
{
// Master Transmitter/Receiver: START condition transmitted.
// Load SMB0DAT with slave device address.
case SMB_START: //0x08
// Master Transmitter/Receiver: repeated START condition transmitted.
// Load SMB0DAT with slave device address
case SMB_RP_START: //0x10
SMB0DAT = TARGET; // Load address of the slave.
SMB0DAT &= 0xFE; // Clear the LSB of the address for the
// R/W bit
SMB0DAT |= SMB_RW; // Load R/W bit
STA = 0; // Manually clear STA bit
rec_byte_counter = 1; // Reset the counter
sent_byte_counter = 1; // Reset the counter
break;
// Master Transmitter: Slave address + WRITE transmitted. ACK received.
// For a READ: N/A
//
// For a WRITE: Send the first data byte to the slave.
case SMB_MTADDACK: //0x18
SMB0DAT = SMB_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
break;
// Master Transmitter: Slave address + WRITE transmitted. NACK received.
// Restart the transfer.
case SMB_MTADDNACK: //0x20
STA = 1; // Restart transfer
break;
// Master Transmitter: Data byte transmitted. ACK received.
// For a READ: N/A
//
// For a WRITE: Send all data. After the last data byte, send the stop
// bit.
case SMB_MTDBACK: //0x28
if (sent_byte_counter <= NUM_BYTES_WR)
{
// send data byte
SMB0DAT = SMB_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
}
else
{
STO = 1; // Set STO to terminate transfer
SMB_BUSY = 0; // And free SMBus interface
}
break;
// Master Transmitter: Data byte transmitted. NACK received.
// Restart the transfer.
case SMB_MTDBNACK: //0x30
STA = 1; // Restart transfer
break;
// Master Receiver: Slave address + READ transmitted. ACK received.
// For a READ: check if this is a one-byte transfer. if so, set the
// NACK after the data byte is received to end the transfer. if not,
// set the ACK and receive the other data bytes.
//
// For a WRITE: N/A
case SMB_MRADDACK: //0x40
if (rec_byte_counter == NUM_BYTES_RD)
{
AA = 0; // Only one byte in this transfer,
// send NACK after byte is received
}
else
{
AA = 1; // More than one byte in this transfer,
// send ACK after byte is received
}
break;
// Master Receiver: Slave address + READ transmitted. NACK received.
// Restart the transfer.
case SMB_MRADDNACK: //0x48
STA = 1; // Restart transfer
break;
// Master Receiver: Data byte received. ACK transmitted.
// For a READ: receive each byte from the slave. if this is the last
// byte, send a NACK and set the STOP bit.
//
// For a WRITE: N/A
case SMB_MRDBACK: //0x50
if (rec_byte_counter < NUM_BYTES_RD)
{
SMB_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
AA = 1; // Send ACK to indicate byte received
rec_byte_counter++; // Increment the byte counter
}
else
{
AA = 0; // Send NACK to indicate last byte
// of this transfer
}
break;
// Master Receiver: Data byte received. NACK transmitted.
// For a READ: Read operation has completed. Read data register and
// send STOP.
//
// For a WRITE: N/A
case SMB_MRDBNACK: //0x58
SMB_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
STO = 1;
SMB_BUSY = 0;
AA = 1; // Set AA for next transfer
break;
// Master Transmitter: Arbitration lost.
case SMB_MTARBLOST: //0x38
FAIL = 1; // Indicate failed transfer
// and handle at end of ISR
break;
// All other status codes invalid. Reset communication.
default:
FAIL = 1;
break;
}
if (FAIL) // If the transfer failed,
{
SMB0CN &= ~0x40; // Reset communication
SMB0CN |= 0x40;
STA = 0;
STO = 0;
AA = 0;
SMB_BUSY = 0; // Free SMBus
FAIL = 0;
}
SI = 0; // Clear interrupt flag
}
//-----------------------------------------------------------------------------
// Support Functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SMB_Write
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Writes a single byte to the slave with address specified by the <TARGET>
// variable.
// Calling sequence:
// 1) Write target slave address to the <TARGET> variable
// 2) Write outgoing data to the <SMB_DATA_OUT> array
// 3) Call SMB_Write()
//
void SMB_Write (void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = SMB0_PAGE;
while (SMB_BUSY); // Wait for SMBus to be free.
SMB_BUSY = 1; // Claim SMBus (set to busy)
SMB_RW = 0; // Mark this transfer as a WRITE
STA = 1; // Start transfer
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector
}
//-----------------------------------------------------------------------------
// SMB_Read
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Reads a single byte from the slave with address specified by the <TARGET>
// variable.
// Calling sequence:
// 1) Write target slave address to the <TARGET> variable
// 2) Call SMB_Write()
// 3) Read input data from <SMB_DATA_IN> array
//
void SMB_Read (void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = SMB0_PAGE;
while (SMB_BUSY); // Wait for bus to be free.
SMB_BUSY = 1; // Claim SMBus (set to busy)
SMB_RW = 1; // Mark this transfer as a READ
STA = 1; // Start transfer
while (SMB_BUSY); // Wait for transfer to complete
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector
}
The main continuously does the following: Sends 3 bytes. The first byte is the device register pointer. Then reads the same register (since the pointer is already set). It does do this.
while (1)
{
TARGET = SLAVE_ADDR; // Target the Slave for next SMBus
// transfer
SMB_DATA_OUT[0] = 0x01; // Device register
SMB_DATA_OUT[1] = 0x0A; // Register MSByte
SMB_DATA_OUT[2] = 0x03; // Register LSbyte
SMB_Write(); // Initiate SMBus write
// SMBus Read Sequence
TARGET = SLAVE_ADDR; // Target the Slave for next SMBus
// transfer
SMB_Read();
}
And here is a trace capture of transfer:
Looks to me like the master receive is sending an extra ACK. So my main focus has been on cases:
SMB_MRADDACK: //0x40
SMB_MRADDNACK: //0x48
SMB_MRDBACK: //0x50
My main focus is more so SMB_MRADDNACK: //0x48 and the number of times it goes through that if statement during the ISR calls. I'm having a little trouble wrapping my head around the exact failure point. So where is this extra ACK coming from? I'll look back here Monday afternoon if I don't figure it out myself by then.
Bonus question: Is there a embedded stack exchange of some sort? Didn't see anything that stood out for me in the communities..
Your trace shows (excluding addressing) three bytes sent and three bytes read. I'm assuming you desired to write three bytes and then only read two bytes. If that's true, then the problem is more than just a spurious ACK because your master continues clocking the third byte in as well.
If you desire to read only two bytes with the sample code from SiLabs1, you need to define NUM_BYTES_RD to 2 instead of the provided 3. That value is used in the SMB_MRADDACK and SMB_MRDBACK states to decide whether to ACK or STOp.
Just in case (since you ask about ACKs instead of extra bytes), if your question is about the final drop in the SDL line on your trace (after the 0xff) because you're afraid that's an extra ACK, then worry not. That is a STO (rises during high SCL) and is correct behavior for a Master terminating a transmission.
Edit: klamb is correct in the comments below below, there is bug in the SMB_MRDBACK state. Saving SMB0DAT and incrementing rec_byte_counter should happen before checking rec_byte_counter against NUM_BYTES_RD. Suprising that got out of SiLabs like that.
case SMB_MRDBACK: //0x50
SMB_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
rec_byte_counter++; // Increment the byte counter
if (rec_byte_counter < NUM_BYTES_RD)
{
AA = 1; // Send ACK to indicate byte received
}
else
{
AA = 0; // Send NACK to indicate last byte
// of this transfer
}
break;