I need to send a UDP broadcast from a RaspberryPi 3 running Windows 10 IoT Core. My code so far:
internal class UdpInterface : IDisposable
{
private UdpClient udpClient;
internal UdpInterface(int localPort)
{
udpClient = new UdpClient(localPort);
udpClient.EnableBroadcast = true;
}
internal void BroadcastMessage(string message, int targetPort)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Broadcast, targetPort);
byte[] bytes = Encoding.ASCII.GetBytes(message);
udpClient.Send(bytes, bytes.Length, ip);
}
public void Dispose()
{
udpClient.Close();
udpClient.Dispose();
}
}
I call it like this from a GPIO pin ValueChanged event:
_udp.BroadcastMessage("Video" + PinMapper(sender.PinNumber), _port);
I tried setting the Internet (Client & Server) capability in package.appxmanifest, and I tried using the DatagramSocket class before.
Do I need some other permissions/capabilities or is something wrong with my code? It did work when sending to target IPs before.
I'm verifying the packet with PacketSender on my dev machine.
Related
A field device (Loxone miniserver) is sending measurements in UDP packets to the public adress of an azure VM and to my local machine, both on port 1234(changed for integrity). On my local machine in the same network as the field device I implemented a test receiver in C# which gets the packets correctly.
On an already running application on an azure VM I added the same receiver code as in the local machine and got no UDP packets.
What I already did on the azure management platform:
- Allowed the incoming port 1234 in the network configuration
- Switched off the firewall
For testing I tried following:
- Implemented a UDP sender on the application in the azure VM which sends on broadcast-IP to port 1234 -> this works!
- Added a packet monitor to the network-interface -> here I see both packages, the internal broadcast and the field device
//Receiver-Code reduced to relevant parts
class Program{
public static void Main(string[] args){
program.Run();
}
public void Run(){
var sync = new LoxoneSyncProcess();
while(true){
sync.readUDP();
Thread.sleep(10000);
}
}
}
class LoxoneSyncProcess{
public LoxoneSyncProcess(){
private UDPSocket c = new UDPSocket();
c.Client(1234);
}
public void readUDP(){
String buffer = c.getDatBuf();
Console.WriteLine(buffer);
//process buffer
}
}
public class UDPSocket{
private Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private const int bufSize = 8 * 1024;
private State state = new State();
private EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0);
private AsyncCallback recv = null;
private String datBuf = "";
public class State
{
public byte[] buffer = new byte[bufSize];
}
public String getDatBuf()
{
String temp = datBuf;
datBuf = "";
return temp;
}
public void Client(int port)
{
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
Receive();
}
private void Receive()
{
_socket.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) =>
{
State so = (State)ar.AsyncState;
int bytes = _socket.EndReceiveFrom(ar, ref epFrom);
_socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so);
datBuf += Encoding.ASCII.GetString(so.buffer, 0, bytes);
//Console.WriteLine("RECV: {0}: {1}, {2}", epFrom.ToString(), bytes, Encoding.ASCII.GetString(so.buffer, 0, bytes));
}, state);
}
}
The code is working, I receive self sent UDP packets to port 1234 on Broadcast-IP, but not from the field device.
Are there any tables like NAT-configurations needed? Or portforewarding? Does azure support public UDP endpoints?
UDP public Endpoint is supported in Azure. Just wanted to check the size of the UDP payload that you use. If the UDP payload is > 1500 bytes then it will not work.
This is by design at the moment as we do not support fragments to public VIP endpoints right now in the vswitch. The recommendation is for customers to keep UDP datagrams to under 1500. There’s really nothing short term we could do to allow fragments through without code changes – they’re fundamentally not supported in the NAT
One thing to note is the mentioning of fragmentation according to Microsoft.
Granted the information is about TCP/IP but MTU obviously affects UDP traffic as well.
Azure and VM MTU
The default MTU for Azure VMs is 1,500 bytes. The Azure Virtual Network stack >will attempt to fragment a packet at 1,400 bytes.
Note that the Virtual Network stack isn't inherently inefficient because it >fragments packets at 1,400 bytes even though VMs have an MTU of 1,500. A >large percentage of network packets are much smaller than 1,400 or 1,500 >bytes.
Source https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-tcpip-performance-tuning
I'm now trying to connect STM32F429 to C# desktop application with ESP8266(in STA mode). I want ESP8266 to be a client and C# to be a Server. However ESP8266 remains failing to find my PC in the same LAN.
Now I have succeeded to use AT command to connect ESP8266 to my Router AP. And I used XAMPP to open a gate on my PC whose address is 192.168.1.11:80, then use the following command (AT+CIPSTART=\"TCP\",\"192.168.1.11\",80") to successfully connect ESP8266 to it(It returned OK to my STM32F429).
Then I wanna replace XAMPP with my C# code to open a TCP server. But I couldn't make it!
As for the C# Code, I have successfully build a connection between two C# programs (The IP Address is 192.168.1.11:80 which is the same as the one mentioned above).But when I tried to use ESP8266 to connect to the same IP and Port, it failed.
I suspected that there might be some wrong conceptions I have got about opening a TCP Listener on certain port in my LAN... I don't know...
The following is my C# code. (The code of STM32 is just a basic Usart code which I won't present here.)
// Code for Server
namespace Tcp_Server
{
public partial class Form1 : Form
{
private TcpListener myListener;
private TcpClient newClient;
public BinaryReader br;
public BinaryWriter bw;
public Form1()
{
InitializeComponent();
Thread myThread = new Thread(ServerA);
myThread.Start();
}
private void ServerA()
{
IPAddress SvrIP = new IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address); // Get the virtual IP of my PC.
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, ip.ToString() });
myListener = new TcpListener(ip, 80); //construct a Tcp Listener.
myListener.Start(); //Tcp Listener start
newClient = myListener.AcceptTcpClient();// Searching for a client...
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, "Connect Successfully" });
while (true)
{
try
{
NetworkStream clientStream = newClient.GetStream();
br = new BinaryReader(clientStream);
string receive = null;
receive = br.ReadString();//读取
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, receive });
}
catch
{
MessageBox.Show("Receving failed...");
}
}
}
// Code for client
namespace Client
{
public partial class Form1 : Form
{
private TcpClient client;
public BinaryReader br;
public BinaryWriter bw;
public Form1()
{
InitializeComponent();
Thread myThread = new Thread(ClientA);
myThread.Start();
}
private void ClientA()
{
IPAddress ip = new IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address); // Get the virtual IP of my PC.
client = new TcpClient(ip.ToString(), 80);
this.Invoke(new AddToTextbox_dg(AddToTextbox), new object[] { tb_ServerStatus, "Connect to Server Successfully!" });
while (true)
{
try
{
NetworkStream clientStream = client.GetStream();
br = new BinaryReader(clientStream);
string receive = null;
receive = br.ReadString();
}
catch
{
MessageBox.Show("Receving failed...");
}
}
}
private void AddToTextbox(TextBox txt, String s)
{
txt.Text += s;
}
private delegate void AddToTextbox_dg(TextBox txt, String s);
private void btn_send_Click(object sender, EventArgs e)
{
NetworkStream clientStream = client.GetStream();
bw = new BinaryWriter(clientStream);
bw.Write(message.Text);
}
}
}
Could somebody please help me with this problem ?
I wonder why I cannot connect ESP8266 to the TcpListener I built on my PC with C#.
What did my PC do when receiving the command:
myListener = new TcpListener(ip, 80);
This project I'm doing is about to transmit the image data I got with Stm32F429 and OV7725 to my PC through ESP8266. I know Usart will be too slow to do that, but now I'm just trying to build the connection. Is there any suggestion you guys could give me about this?
First, make sure no other application on your pc is listening to port 80. if so, you have to change it.
Second, try setting the ip of the TCPListener to local host "127.0.0.1". you will be able to reach this server by connecting to the ip of your PC.
I have checked the used IP in command window as below:
Command Window for checking IP usage
And I remain the IP address which ESP8266 will try to access to be 192.168.1.11:1900 which is the virtual IP of my PC in the LAN as below:
Address ESP8266 try to access
And change the IP C# will try to create a TCPListener on:
C# code
Is this what you mean? Thank you.
I have tried implementing UDP hole punch from this theory:
A rendezvous server (S) is reachable on UDP by client (A) and client (B).
Clients A and B send a registration package each to S. S reads public IP and outer port and stores it.
S sends A-info (endPointA) to B and B-info (endPointB) to A.
With this information A can send to B's endPoint and B can send to A's endPoint.
server S is python 3 and clients A and B are C#
So far the theory. Here is what works:
S can send as many messages to A and B as it likes on their public endPoint.
A and B can send to each other on innerIP:localPort if they are behind the same router ONLY!
Here is what does not work:
A cannot send to B nor B to A with their public endPointA / endPointB
even if I create a new socket on the server S, it cannot get a message through to these endPoints
This last limitation makes me think there is some "lock" on routers that only allow the original socket on S to send to the clients(?)
So my question is: what now?
Is there some socket option, socket flag, socket anything that needs to be set to fix this?
I have even tried making a script on the server S that sends to the clients public IP on all ports from 32000-65535 with no messages coming through.
Code for server:
def ServerUdpStart(host, port):
"""Start up the server"""
global myServerUdp
success = True
try :
myServerUdp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error as msg:
print('UDP Failed to create socket. Error Code:', str(msg[0]), 'Message', msg[1])
success = False
# Bind socket to local host and port
try:
myServerUdp.bind( (host, port) )
except socket.error as msg:
print('UDP bind failed. Error Code : ', str(msg[0]), 'Message', msg[1])
success = False
return success
def ServerUdpReceiveData():
"""Incoming UDP data (runs in a thread)"""
global myServerUdp
if myServerUdp != None:
d = myServerUdp.recvfrom(1024)
data = d[0]
addr = d[1] # source tuple (ip, port) to store for clients
if data:
incomingUdpMessage(addr, data) # handle incoming data
Code for a client:
public class SocketServerUdpHandler{
// ports
private int _port = 0;
private int _localAssignedPort = 0;
// udp client
private UdpClient _clientUdp = null;
private IPEndPoint recvEndP = new IPEndPoint( IPAddress.Any, 0);
//********** START **********
public bool StartUdp(int po){
// port set by user
_port = po;
// client
bool created = CreateClient();
// start it up
if(created){
FindLocalAssignedPort();
StartListen();
}
return created;
}
//********** LISTENER **********
private bool CreateClient(){
// state
bool success = true;
try{
// udp client
_clientUdp = new UdpClient();
}catch(Exception e){
success = false;
}
return success;
}
private void StartListen(){
// listen
_clientUdp.BeginReceive(new AsyncCallback(ReceiveCallback), null);
}
private void ReceiveCallback(IAsyncResult ar){
// read incoming
byte[] receiveBytes = _clientUdp.EndReceive(ar, ref recvEndP);
// handle bytes ...
// listen
StartListen();
}
private void FindLocalAssignedPort(){
IPEndPoint tmpEndP = new IPEndPoint( IPAddress.Parse("127.0.0.1"), 10001 );
byte[] msgByte = new byte[] {(byte) 9};
_clientUdp.Client.SendTo(msgByte, tmpEndP);
_localAssignedPort = ((IPEndPoint) _clientUdp.Client.LocalEndPoint).Port;
}
//********** SEND TO **********
public void writeSocketToEndPoint(IPEndPoint ipEndP, byte[] bytes){
_clientUdp.Client.SendTo(bytes, ipEndP);
}
}
I wrote two small applications (a client and a server) to test UDP communication and I found the 'connection' (yeah, I know, there's no real connection) between them gets lost frecuently for no reason.
I know UDP is an unreliable protocol, but the problem here does not seem the losing of packets, but the losing of the communication channel between the apps.
Here's client app code:
class ClientProgram
{
static void Main(string[] args)
{
var localEP = new IPEndPoint(GetIPAddress(), 0);
Socket sck = new UdpClient(localEP).Client;
sck.Connect(new IPEndPoint(IPAddress.Parse("[SERVER_IP_ADDRESS]"), 10005));
Console.WriteLine("Press any key to request a connection to the server.");
Console.ReadLine();
// This signals the server this clients wishes to receive data
SendData(sck);
while (true)
{
ReceiveData(sck);
}
}
private static void ReceiveData(Socket sck)
{
byte[] buff = new byte[8];
int cnt = sck.Receive(buff);
long ticks = BitConverter.ToInt64(buff, 0);
Console.WriteLine(cnt + " bytes received: " + new DateTime(ticks).TimeOfDay.ToString());
}
private static void SendData(Socket sck)
{
// Just some random data
sck.Send(new byte[] { 99, 99, 99, 99 });
}
private static IPAddress GetIPAddress()
{
IPHostEntry he = Dns.GetHostEntry(Dns.GetHostName());
if (he.AddressList.Length == 0)
return null;
return he.AddressList
.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
.FirstOrDefault();
}
}
Here's the server app code:
class ServerProgram
{
private static int SLEEP = 5;
static void Main(string[] args)
{
// This is a static IP address
var localEP = new IPEndPoint(GetIPAddress(), 10005);
Socket sck = new UdpClient(localEP).Client;
// When this methods returs, a client is ready to receive data
var remoteEP = ReceiveData(sck);
sck.Connect(remoteEP);
while (true)
{
SendData(sck);
System.Threading.Thread.Sleep( ServerProgram.SLEEP * 1000);
}
}
private static EndPoint ReceiveData(Socket sck)
{
byte[] buff = new byte[8];
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int cnt = sck.ReceiveFrom(buff, ref clientEP);
Console.WriteLine(cnt + " bytes received from " + clientEP.ToString());
return (IPEndPoint)clientEP;
}
private static void SendData(Socket sck)
{
DateTime n = DateTime.Now;
byte[] b = BitConverter.GetBytes(n.Ticks);
Console.WriteLine("Sending " + b.Length + " bytes : " + n.TimeOfDay.ToString());
sck.Send(b);
}
private static IPAddress GetIPAddress()
{
// Same as client app...
}
}
(this is just test code, don't pay attention to the infinite loops or lack of data validation)
The problem is after a few messages sent, the client stops receiving them. The server keeps sending, but the client gets stuck at sck.Receive(buff). If I change SLEEP constant to a value higher than 5, the 'connection' gets lost after 3 or 4 messages most of the time.
I can confirm the client machine doesn´t receive any packet when the connection is lost since I use Wireshark to monitor the communication.
The server app runs on a server with direct connection to Internet, but the client is a machine in a local network, behind a router. None of them has a firewall running.
Does anyone have a clue what could be happening here?
Thank you!
EDIT - Additional data:
I tested the client app in several machines in the same network and the connection get lost always. I also tested the client app in other network behind other router and there is no problem there. My router is a Linksys RV042 and never had any problem with it, in fact, this app is the only one with problems.
PROBLEM SOLVED - SHORT ANSWER: It was a hardware problem.
I don't see any overt problems in the source code. If it is true that:
The server keeps sending packets (confirmed by WireShark on the server)
The client never receives the packets (confirmed by WireShark on the client)
..then the problem could be related to networking equipment between the two machines, which don't always handle UDP flows as expected especially when behind routers/firewalls.
I would recommend the following approach to troubleshooting:
Run client & server on the same system and use the loopback interface (confirm UDP code works on the loopback)
Run the client & server on two different systems that are plugged into the same Ethernet switch (confirm that UDP communication works switch-local)
If everything works switch-local you can be fairly sure you have a network configuration problem.
Alright, so I'm trying to connect to UDP trackers using c#, but I never get a response. I also don't get any errors. Here's my code.
namespace UDPTester
{
class MainClass
{
public static bool messageReceived = false;
public static Random Random = new Random();
public static void LOG(string format, params object[] args)
{
Console.WriteLine (format,args);
}
public static void Main (string[] args)
{
LOG ("Creating Packet...");
byte[] packet;
using(var stream = new MemoryStream())
{
var bc = new MiscUtil.Conversion.BigEndianBitConverter();
using(var br = new MiscUtil.IO.EndianBinaryWriter(bc,stream))
{
LOG ("Magic Num: {0}",(Int64)0x41727101980);
br.Write (0x41727101980);
br.Write((Int32)0);
br.Write ((Int32)Random.Next());
packet = stream.ToArray();
LOG ("Packet Size: {0}",packet.Length);
}
}
LOG ("Connecting to tracker...");
var client = new System.Net.Sockets.UdpClient("tracker.openbittorrent.com",80);
UdpState s = new UdpState();
s.e = client.Client.RemoteEndPoint;
s.u = client;
StartReceiving(s);
LOG ("Sending Packet...");
client.Send(packet,packet.Length);
while(!messageReceived)
{
Thread.Sleep(1000);
}
LOG ("Ended");
}
public static void StartReceiving(UdpState state)
{
state.u.BeginReceive(ReceiveCallback,state);
}
public static void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u;
IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e;
Byte[] receiveBytes = u.EndReceive(ar, ref e);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
LOG("Received: {0}", receiveString);
messageReceived = true;
StartReceiving((UdpState)ar.AsyncState);
}
}
public class UdpState
{
public UdpClient u;
public EndPoint e;
}
}
I was using a normal BinaryWriter, but that didn't work, and I read somewhere that it wants it's data in BigEndian.
This doesn't work for any of the UDP trackers I've found, any ideas why I'm not getting a response? Did they maybe change the protocol and not tell anyone? HTTP trackers all work fine.
Trackers I've tried
udp://tracker.publicbt.com:80
udp://tracker.ccc.de:80
udp://tracker.istole.it:80
Also, I'm not interested in using MonoTorrent(and when I was using it, the UDP didn't work anyways).
Protocol Sources
http://xbtt.sourceforge.net/udp_tracker_protocol.html
http://www.rasterbar.com/products/libtorrent/udp_tracker_protocol.html
UDP is a connectionless protocol, so you won't see any errors if packets are lost or dropped at the destination.
Try following diagnostic steps:
Use packet sniffer (Wireshark is a good one) to check that UDP packets are leaving the machine.
Install some working BitTorrent client, check if it can communicate with the tracker and if yes, use packet sniffer to see how the packets sent by the working client differ from the packets your code generates.
If working client also can not communicate with the tracker, but the UDP traffic is leaving your machine, the UDP packets are likely dropped by a firewall. You can try 'traceroute' tool to diagnose where your packets are dropped (this is not always 100% reliable, because sometimes firewalls drop UDP packets generated by traceroute and do not drop normal UDP traffic).