I have been searching the internet for a week or two now to find a UDP client program that can send and receive at the same time but there is nothing on this subject for c#. In the last few days I have tried create a UDP client with a thread that receives.
Sending UDP packets works great but the program can not receive for the server i sent to, I believe the server is sending all packets to a different port.
How do i fix this program?
Is there an easier way to do UDP programming like StreamReader and StreamWriter for TCP?
static void CONNECTudp()
{
Console.WriteLine("Host:");
IPAddress ipAddress = Dns.Resolve(Console.ReadLine()).AddressList[0];
Console.WriteLine("Port:");
int Port = int.Parse(Console.ReadLine());
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, Port);
Thread UDPthread = new Thread(() => CONNECTudpthread(ipEndPoint));
UDPthread.Start();
UdpClient udp = new UdpClient();
do
{
Byte[] sendBytes = Encoding.ASCII.GetBytes(Console.ReadLine());
udp.Send(sendBytes, sendBytes.Length, ipEndPoint);
} while (true);
}
static void CONNECTudpthread(IPEndPoint ipEndPoint)
{
UdpClient udp = new UdpClient();
do
{
try
{
Byte[] receiveBytes = udp.Receive(ref ipEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
catch (Exception)
{
}
} while (true);
}
Since UDP is message-oriented and not stream-oriented, there's not really a practical way to use StreamReader and StreamWriter with UDP. Sticking with the message-oriented I/O as in your example is best.
The problem in your code is that you are using two different UdpClient instances for sending and receiving. You don't show the UDP server code, so I can't guarantee that's correct either. But if it is, then if you fix your code to be something more like the following, it should work:
static void CONNECTudp()
{
Console.WriteLine("Host:");
IPAddress ipAddress = Dns.Resolve(Console.ReadLine()).AddressList[0];
Console.WriteLine("Port:");
int Port = int.Parse(Console.ReadLine());
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, Port);
// Bind port immediately
UdpClient udp = new UdpClient(0);
// Pass UdpClient instance to the thread
Thread UDPthread = new Thread(() => CONNECTudpthread(udp));
UDPthread.Start();
do
{
Byte[] sendBytes = Encoding.ASCII.GetBytes(Console.ReadLine());
udp.Send(sendBytes, sendBytes.Length, ipEndPoint);
} while (true);
}
static void CONNECTudpthread(UdpClient udp)
{
do
{
try
{
// Though it's a "ref", the "remoteEP" argument is really just
// for returning the address of the sender.
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = udp.Receive(ref ipEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
catch (Exception)
{
}
} while (true);
}
Related
I am using USR-TCP232 LAN Modules for an embedded project.
I have a tool to query those modules made by the manufacturer, it works great.
But, I want it in my code in C#. So, I decided to make one for myself. I believe I am so close but I guess a small glitch which gives me hard times and I need somebody to put some shed light on.
I can send a UDP broadcast and I can observe the traffic via "WireShark".
It is quite similar with the original tool. But, I can't receive the answered data sent by the devices on the network in my code.
Console application in C#
using System;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
namespace UDPer
{
class Program
{
static void Main(string[] args)
{
UDPer udp = new UDPer();
udp.Starter();
ConsoleKeyInfo cki;
do
{
if (Console.KeyAvailable)
{
cki = Console.ReadKey(true);
switch (cki.KeyChar)
{
case 's':
udp.Send("0123456789012345678901234567890123456789");
break;
case 'x':
udp.Stop();
return;
}
}
Thread.Sleep(10);
} while (true);
}
}
class UDPer
{
private Socket udpSock;
private byte[] buffer;
public void Starter()
{
//Setup the socket and message buffer
udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpSock.Bind(new IPEndPoint(IPAddress.Any, 0));
udpSock.EnableBroadcast = true;
buffer = new byte[1024];
udpSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//udpSock.ExclusiveAddressUse = false; // only if you want to send/receive on same machine.
//The socket must not be bound or connected.
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}
public void Stop()
{
try
{
udpSock.Close();
Console.WriteLine("Stopped listening");
}
catch { /* don't care */ }
}
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
//Get the received message.
Socket recvSock = (Socket)iar.AsyncState;
recvSock.EnableBroadcast = true;
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
byte[] localMsg = new byte[msgLen];
Array.Copy(buffer, localMsg, msgLen);
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
//Handle the received message
Console.WriteLine("Recieved {0} bytes from {1}:{2}",
msgLen,
((IPEndPoint)clientEP).Address,
((IPEndPoint)clientEP).Port);
//Do other, more interesting, things with the received message.
string message = Encoding.ASCII.GetString(localMsg);
Console.WriteLine("Message: {0} ", message);
}
catch (ObjectDisposedException)
{
//expected termination exception on a closed socket.
}
}
public void Send(string message)
{
UdpClient udp = new UdpClient(1500);
var ipEndPoint = new IPEndPoint(IPAddress.Broadcast, 1500);
byte[] data = Encoding.ASCII.GetBytes(message);
udp.Send(data, data.Length, ipEndPoint);
udp.Close();
}
}
}
Wireshark capture
Note that: This Wireshark capture is exactly the same as the original tool does.
Some definitions:
My PC where C# application resides: 192.168.65.82
LAN Module IP Address: 192.168.65.8
Ports must be 1500 which is all OK.
Send payload for querying LAN Modules;
"0123456789012345678901234567890123456789"
So, I have tried tons of different options one by one but no jo so far.
What am I missing here?
A socket always has a dedicated port. Passing an IPEndPoint with port number 0 doesn't mean that you receive packets send to any port. Instead you are binding to a port assigned by the underlying service provider.
udpSock.Bind(new IPEndPoint(IPAddress.Any, 0));
If you do not care which local port is used, you can create an IPEndPoint using 0 for the port number. In this case, the service provider will assign an available port number between 1024 and 5000
https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.bind(v=vs.110).aspx
You need to use
udpSock.Bind(new IPEndPoint(IPAddress.Any, 1500));
I'm new to C# UDP coding and I have some 'strange' behaviour when using an UDP client locally on my pc.
I want to send UDP data from one port (11000) on my pc to another port (12000) on the same pc.
This is a snippet from my code :
public class MyClass
{
//Creates a UdpClient for reading incoming data.
private UdpClient udpClient;
private Thread thread;
private const String IPADDR = "127.0.0.1";
public MyClass()
{
udpClient = new UdpClient(11000);
udpClient.Connect(IPAddress.Parse(IPADDR), 12000);
this.thread = new Thread(new ThreadStart(this.Execute));
this.thread.Name = "Udp";
this.thread.Start();
SendData("The quick brown fox jumps over the lazy dog");
}
private void Execute()
{
try
{
// Blocks until a message returns on this socket from a remote host.
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);
Console.WriteLine("Data received");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void SendData(String data)
{
Console.WriteLine("Sending...");
try
{
this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0}", e.Message));
}
}
}
If I run this, I get an exception :
Sending...
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP)
at System.Net.Sockets.UdpClient.Receive(IPEndPoint& remoteEP)
at test.MyClass.Execute() in C:\Temp\test\Class1.cs:line 40
The exception seems to occur on this line :
Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);
At the moment of the SendData(), the Receive is throwing the exception. When not doing the send, I don't get the exception. It looks like the send is causing the receive to return with an exception.
When I use the real ip address of my pc, I have the same behaviour. However, when I use any other ip address, even if it's unassigned to any pc (e.g. 192.168.10.10), it's working well : it sends the string and the Receive() keeps waiting for incoming data.
The error happens because there is no socket open on the port to which you are sending.
For the purposes of simply testing UDP communications, you can fix your code example simply by changing the port to which you are sending. I.e. change the Connect() method call to this:
udpClient.Connect(IPAddress.Parse(IPADDR), 11000);
This will cause the socket to send to itself. Your code will work successfully with just this change.
For the record, here is about the simplest possible demonstration code that uses UdpClient:
UdpClient client = new UdpClient(0, AddressFamily.InterNetwork);
byte[] datagram = Encoding.ASCII.GetBytes("hello world!");
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)client.Client.LocalEndPoint).Port);
client.Send(datagram, datagram.Length, ipEndPoint);
datagram = client.Receive(ref ipEndPoint);
Console.WriteLine("Received: \"" + Encoding.ASCII.GetString(datagram) + "\"");
Of course, in a real network I/O situation, you will have two endpoints, each bound to its own local port, sending to the other endpoint's port. So neither your code example, nor this simpler one I present is very useful as an actual working program. But it does allow you to learn some things about how the socket API works.
You are trying to send from one socket (UdpClient which is socket wrapper) to itself. Thats not how the things work in UDP (nor in other IP protocols). You need 2 sockets. One for sending one for receiving. Connect method is poorly named since UDP protocol is conectionless but thats not your fault.
Other than that you need to put socket in listening state before sending to it. So you first need to start thread that listens and then send.
You need to better design your program but this will work:
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
}
}
public class MyClass
{
//Creates a UdpClient for reading incoming data.
private UdpClient udpClient;
private UdpClient recipient;
private Thread thread;
private const String IPADDR = "127.0.0.1";
public MyClass()
{
recipient = new UdpClient(new IPEndPoint(IPAddress.Parse(IPADDR), 12000));
this.thread = new Thread(new ThreadStart(this.Execute));
this.thread.Name = "Udp";
this.thread.Start();
udpClient = new UdpClient(11000);
udpClient.Connect(IPAddress.Parse(IPADDR), 12000);
SendData("The quick brown fox jumps over the lazy dog");
}
private void Execute()
{
try
{
// Blocks until a message returns on this socket from a remote host.
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Parse(IPADDR), 11000);
Byte[] receiveBytes = this.recipient.Receive(ref remoteIpEndPoint);
Console.WriteLine("Data received: " + Encoding.ASCII.GetString(receiveBytes));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void SendData(String data)
{
Console.WriteLine("Sending...");
try
{
this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0}", e.Message));
}
}
}
tried to solve this alone for the past I don't even know but no googling will help me here, I would need some advice with this one. I am receiving UDP packets from another PC on my local network every 10 seconds, can see them in wireshark but the application is stuck on the udpClient.Receive() line. The multicast group and port are the right values, checked in main() n+1 times. Please suggest a solution if you have any idea that might help. Thanks.
(I'm trying to receive the server's information so that th application can automaticaly start to communicate vith it via TCP)
class MulticastListener {
private UdpClient udpClient;
private IPEndPoint remoteEndPoint;
IPAddress multicastIP;
private int port;
public MulticastListener(ref IPAddress multicastIP, int port) {
remoteEndPoint = new IPEndPoint(IPAddress.Any, port);
this.multicastIP = multicastIP;
this.port = port;
udpClient = new UdpClient();
udpClient.Client.Bind(remoteEndPoint);
}
public IPEndPoint GetServer() {
try {
udpClient.JoinMulticastGroup(multicastIP);
} catch (ObjectDisposedException e) {
Console.WriteLine("ERROR: The underlying socket has been closed!");
} catch (SocketException e) {
Console.WriteLine("ERROR: An error occurred when accessing the socket!");
} catch (ArgumentException e) {
Console.WriteLine("ERROR: The IP address is not compatible with the AddressFamily value that defines the addressing scheme of the socket!");
}
Byte[] serverInfoBytes = udpClient.Receive(ref remoteEndPoint);
Stream stream = new MemoryStream(serverInfoBytes); //receives a serialised IPEndpoint object
BinaryFormatter formatter = new BinaryFormatter();
udpClient.Close();
return (IPEndPoint)formatter.Deserialize(stream);
}
}
As I commented, your code works fine for me 100% as is. I would check you are sending on the same subnet you are receiving on. Perhaps your sender is not configured to the right interface?
Perhaps it would help to try out a different sender, here is what I used to test:
static void Main(string[] args)
{
//Configuration
var interfaceIp = IPAddress.Parse("192.168.9.121");
var interfaceEndPoint = new IPEndPoint(interfaceIp, 60001);
var multicastIp = IPAddress.Parse("230.230.230.230");
var multicastEndPoint = new IPEndPoint(multicastIp, 60001);
//initialize the socket
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.ExclusiveAddressUse = false;
socket.MulticastLoopback = false;
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
MulticastOption option = new MulticastOption(multicastEndPoint.Address, interfaceIp);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, option);
//bind on a network interface
socket.Bind(interfaceEndPoint);
//initialize args for sending packet on the multicast channel
var sockArgs = new SocketAsyncEventArgs();
sockArgs.RemoteEndPoint = multicastEndPoint;
sockArgs.SetBuffer(new byte[1234], 0, 1234);
//send an empty packet of size 1234 every 3 seconds
while (true)
{
socket.SendToAsync(sockArgs);
Thread.Sleep(3000);
}
}
The following code sends a packet on port 15000:
int port = 15000;
UdpClient udp = new UdpClient();
//udp.EnableBroadcast = true; //This was suggested in a now deleted answer
IPEndPoint groupEP = new IPEndPoint(IPAddress.Broadcast, port);
string str4 = "I want to receive this!";
byte[] sendBytes4 = Encoding.ASCII.GetBytes(str4);
udp.Send(sendBytes4, sendBytes4.Length, groupEP);
udp.Close();
However, it's kind of useless if I can't then receive it on another computer. All I need is to send a command to another computer on the LAN, and for it to receive it and do something.
Without using a Pcap library, is there any way I can accomplish this? The computer my program is communicating with is Windows XP 32-bit, and the sending computer is Windows 7 64-bit, if it makes a difference. I've looked into various net send commands, but I can't figure them out.
I also have access to the computer (the XP one)'s local IP, by being able to physically type 'ipconfig' on it.
EDIT: Here's the Receive function I'm using, copied from somewhere:
public void ReceiveBroadcast(int port)
{
Debug.WriteLine("Trying to receive...");
UdpClient client = null;
try
{
client = new UdpClient(port);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
IPEndPoint server = new IPEndPoint(IPAddress.Broadcast, port);
byte[] packet = client.Receive(ref server);
Debug.WriteLine(Encoding.ASCII.GetString(packet));
}
I'm calling ReceiveBroadcast(15000) but there's no output at all.
Here is the simple version of Server and Client to send/receive UDP packets
Server
IPEndPoint ServerEndPoint= new IPEndPoint(IPAddress.Any,9050);
Socket WinSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
WinSocket.Bind(ServerEndPoint);
Console.Write("Waiting for client");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0)
EndPoint Remote = (EndPoint)(sender);
int recv = WinSocket.ReceiveFrom(data, ref Remote);
Console.WriteLine("Message received from {0}:", Remote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Client
IPEndPoint RemoteEndPoint= new IPEndPoint(
IPAddress.Parse("ServerHostName"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
Iam trying to send a message (via UDP) from my client to my server. The server should answer this message and if the client receives this answer he should print out a message.
If i run the client and server on my local network everything works fine.
If i try to connect through the internet from another PC outside my network the server receives the request of the client, sends an answer back, but the client never receives this answer. The client and the server are both behind a NAT but i portforwarded the ports at the server´s NAT and the server got its own DNS. I already tried NAT traversal but it gives me the same IP and port adress as the IPEndPoint of the server, after receiveing the request of the client, does.
I´ve got no idea how to fix this, so any guidance would be much appreciated.
Client
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
object[] oData = {1};
sendData(oData, 0,0, "Li");
while (true)
{
Console.ReadLine();
}
}
private void receiveData()
{
string receivePort = 8080;
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.ReceiveTimeout = 1000;
IPEndPoint end = new IPEndPoint(IPAddress.Any, receivePort);
client.Bind(end);
while (true)
{
try
{
byte[] data = new byte[1024];
client.Receive(data, 0, data.Length, SocketFlags.None);
object[] receivedObj = Deserialize(data);
string sType = (string)receivedObj[3];
if (sType == "Li")
{
console.WriteLine("received Li");
}
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
public static void sendData(object[] oData, int iFrom, int iTo, string sType)
{
string sendPort = 17171;
UdpClient client = new UdpClient();
string IP = "ThisIsTheDNSofmyServer.com"; //ServerDNS
//string IP = "192.168.xxx.xxx"; //serverIP in LAN
if (IP.StartsWith("T"))
{
IP = (Dns.GetHostAddresses(IP))[0].ToString();
}
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
oData[1] = iFrom;
oData[2] = iTo;
oData[3] = sType;
Byte[] data = Serialize(oData);
client.Send(data, data.Length, remoteEndPoint);
}
The server´s code is almost the same:
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
while (true)
{
Console.ReadLine();
}
}
private static void ReceiveData()
{
int receivePort = 17171;
UdpClient client = new UdpClient(receivePort);
while (true)
{
try
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
data = client.Receive(ref anyIP);
object[] receivedObj = Deserialize(data);
//if I receive data send an Answer
sendData(receivedObj, 0,0,"Li",anyIP.Address.ToString());
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
private static void sendData(object[] oData, int iFrom, int iTo, string sType, string IP)
{
int sendPort = 8080;
object[] paket = { oData, iFrom, iTo, sType };
UdpClient client = new UdpClient();
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
client.Send(data, data.Length, remoteEndPoint);
}
i believe this is a port cofniguration issue,
8080 is almost likely to be configured as alternate http
"The UdpClient you use to receive datagrams must be created using the multicast port number" from MSDN
Hope this helps and good luck
Krishna
You do not need to do anything unordinary to traverse NAT in the setup you described, you just need to send it from the server back to your client; specifically: you must send back to the end point, i.e. IP and port, you received it on.
client.Send(data, data.Length, remoteEndPoint); // remoteEndPoint is the IPEndPoint you got the datagram on