c# - receive UDP packet in multiple instances - c#

When I start multiple instances of application listening on the same UDP port, only the last receives datagrams. Is there any way to send data to all instances other than sending broadcast (broadcasts are received in all instances)?
My application (commandline):
UdpClient client = new UdpClient();
client.Client.SetSocketOption(
SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.Bind(new IPEndPoint(0, 7894));
client.EnableBroadcast = true;
Console.WriteLine("Press key to send datagram");
while (true)
{
if (client.Available > 0)
{
IPEndPoint ep = null;
client.Receive(ref ep);
Console.WriteLine("Received");
}
if (Console.KeyAvailable)
{
Console.ReadKey();
client.Send(new byte[] { 1 }, 1, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7894));
Console.WriteLine("Sent");
}
}

A port can only been owned by one application/process at a time, so a datagram sent to that port can only be received by one instance.
A clean way would be for each listener to use an ephemeral port and register it with the sender application.

Related

A socket Listener which listens but it doesn´t know the port of the Sender in C#

I´m trying to make a Windows Service which waits a conexion but not in a determinate port. It has to wait a conexion and then, get the port which the sender is trying to connect. The check if the port is free is done by me in the Sender part.
Listener:
Here is where I need help. I need to do something to don´t need a port to inicializate the conexion.
{
// Get Host IP Address that is used to establish a connection
// In this case, we get one IP address of localhost that is IP : 127.0.0.1
// If a host has multiple addresses, you will get a list of addresses
IPHostEntry host = Dns.GetHostEntry("localhost");
IPAddress ipAddress = host.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
try
{
// Create a Socket that will use Tcp protocol
Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// A Socket must be associated with an endpoint using the Bind method
listener.Bind(localEndPoint);
// Specify how many requests a Socket can listen before it gives Server busy response.
// We will listen 10 requests at a time
listener.Listen(10);
Console.WriteLine("Waiting for a connection...");
Socket handler = listener.Accept();
// Incoming data from the client.
string data = null;
byte[] bytes = null;
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
//_installerProcess = (Process) BinarySerialization.Deserializate(bytes);
//Console.WriteLine("Proceso recibido");
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
break;
}
{...}
Sender:
Here is where i check te port and where I send the data.
public static void StartClient(String toSend)
{
byte[] bytes = new byte[1024];
try
{
// Connect to a Remote server
// Get Host IP Address that is used to establish a connection
// In this case, we get one IP address of localhost that is IP : 127.0.0.1
// If a host has multiple addresses, you will get a list of addresses
IPHostEntry host = Dns.GetHostEntry("localhost");
IPAddress ipAddress = host.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, FreeTcpPort() );
// Create a TCP/IP socket.
Socket sender = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
// Connect to Remote EndPoint
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes(toSend);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
{...}
}
static int FreeTcpPort()
{
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}

Calling Socket.Accept() Returns Type initialization error

I am creating a simple networking application that allows one client to connect to the host and sends and recieves data between the two in a while loop. I got most of my code from MSDN, however when I run it, right after Socket.Accept() is called, the form stops running and a TypeInitialization Error is raised. Here is my code:
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, HostingPort);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
Socket handler = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
handler = listener.Accept();
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
byte[] trimmedData = new byte[bytesRec];
Array.Copy(bytes, trimmedData, bytesRec);
string data = Encoding.ASCII.GetString(bytes));
// Show the data on the console.
Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(foo);
handler.Send(msg);
}
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (Exception) { }
}
This is the function that controls everything. Can you find the error, or if there is a proven way to complete this, I'm fine with starting over from scratch. Thank you in advance.

Multicast packets: sending and receiving issues

In my adaption of a few multicast tutorials, I changed my method of sending packets.
In my case, I create a queue of packets of size bytes[1024], after which it is sent via Socket.Send() over all online network adapters
Problem:
When sending, another method called receiveMessage() is running on a separate thread. Using Socket.Bind(), it captures packets, but only 1 packet is captured.
Am I doing too much processing thus delaying (and losing) the packets received?
UPDATE
I am considering adding a queue for incoming packets, thus 1 threads captures and stores, the second processes the packets.
SendMethod
Socket _listener_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
foreach (IPAddress localIP in Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
{
//handle image and files
_listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_MultiIP, localIP));
_listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 1);
_listener_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_listener_socket.MulticastLoopback = true;
_listener_socket.Connect(new IPEndPoint(_MultiIP, _PORT));
int count = MSGS_TO_SEND.Count;
while (count > 0)
{
count--;
byte[] temp = (byte[])(MSGS_TO_SEND.Dequeue());
_listener_socket.Send(temp, _BYTE_BUFFER_SIZE, SocketFlags.None);
MSGS_TO_SEND.Enqueue(temp);
}
//----------------------------------------------
//-------------------SEND DATA------------------
//----------------------------------------------
}
_listener_socket.Close();
Receive method
//initialise multicast group and bind to interface
Socket _sender_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _PORT);
_sender_socket.Bind(ipep);
IPAddress localip = _MultiIP;
_sender_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(localip, IPAddress.Any));
//{
while (_sender_socket.IsBound && !bStop)
{
byte[] b = new byte[_BYTE_BUFFER_SIZE];
_sender_socket.Receive(b);
char[] chars = new char[_BYTE_BUFFER_SIZE];
System.Buffer.BlockCopy(b, 0, chars, 0, b.Length);
string _message = new string(chars).Trim();
string ip = _message.Substring(0, _message.IndexOf("~"));
_message = _message.Remove(0, _message.IndexOf("~") + 1);
string _flag = _message.Substring(0, _message.IndexOf("~"));
_message = _message.Remove(0, _message.IndexOf("~") + 1);
_message = _message.Replace("\0", string.Empty);
ip = "1.0";
icount++;
handleData(ip, _flag, _message);
}
If you wan't to try, here is a fully working example: https://github.com/efaruk/playground/tree/master/Multicasting
You can use those re-usable components (MulticastSender, MulticastReceiver,) in your project if you whish...
The sender doesn't have to bind or add membership. Any datagram socket can send to a multicast address. The receiver needs to add membership to the multicast address. The sender and receiver also need to agree upon the port (receiver should be bound to the port.)
Your Multicast Options in each example have the arguments reversed.
The sockets already have buffering from the kernel, so you don't need to complicate your code with message queues.

UDP multicasting. C#

I try to send message to all members of the group. Sender:
// Create socket
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Multicast IP-address
IPAddress ip = IPAddress.Parse("224.168.55.25");
// Join multicast group
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip));
// TTL
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
// Create an endpoint
IPEndPoint ipep = new IPEndPoint(ip, 4567);
// Connect to the endpoint
s.Connect(ipep);
// Scan message
while (true)
{
byte[] buffer = new byte[1024];
string msg = Console.ReadLine();
buffer = Encoding.ASCII.GetBytes(msg);
s.Send(buffer, buffer.Length, SocketFlags.None);
if (msg.Equals("Bye!", StringComparison.Ordinal))
break;
}
// Close socket
s.Close();
Receiver:
// Create new socket
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Create IP endpoint
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 4567);
// Bind endpoint to the socket
s.Bind(ipep);
// Multicast IP-address
IPAddress ip = IPAddress.Parse("224.168.55.25");
// Add socket to the multicast group
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
// Receive messages
while (true)
{
byte[] data = new byte[1024];
s.Receive(data);
string str = System.Text.Encoding.ASCII.GetString(data, 0, data.Length);
Console.WriteLine(str.Trim());
if (str.Equals("Bye!", StringComparison.Ordinal))
{
break;
}
}
I don't uderstand why there is a lot of free space between messages when I print them to screen on the client side? Why loop in the Receiver program doesn't stop after receiveing message Bye!? How can I fix this problems?
Thank you very much!
You are creating a udp socket. Udp sockets are not connection oriented. So it just receives messages and has no idea about the state of the sender. Even if the sender socket closes, the receiver would keep on listening.
I hope I have understood your question correctly.
if (strData.Trim().Equals("Bye!", StringComparison.Ordinal))
{
Console.WriteLine("that's right");
break;
}
Socket.Receive() return the bytes received you should use the return value to generate the string, or you will get a string with the length of 1024 and Trim cannot handle it.
int len = s.Receive(data);
string str = System.Text.Encoding.ASCII.GetString(data, 0, len);

Get client IP from UDP packages received with UdpClient

I am developing an action multiplayer game with the help of the System.Net.Sockets.UdpClient class.
It's for two players, so one should open a server and wait for incoming connections. The other player inputs the host IP and tries to send a "ping", to make sure a connection is possible and there is an open server. The host then responds with a "pong".
Once the game is running, both have to send udp messages to each other, so they both need the opponents ip address.
Of course the server could also input the clients IP, but that seems unneccessary to me.
How can I get the clients IP from the udp package when the "ping" message is received?
Here is my receiving code (server waiting for ping):
private void ListenForPing()
{
while (!closeEverything)
{
var deserializer = new ASCIIEncoding();
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] recData = udp.Receive(ref anyIP);
string ping = deserializer.GetString(recData);
if (ping == "ping")
{
Console.WriteLine("Ping received.");
InvokePingReceiveEvent();
}
}
}
In your example, when a client connects, the anyIP IPEndPoint object will contain the address and port of the client connection.
private void ListenForPing()
{
while (!closeEverything)
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] recData = udp.Receive(ref anyIP);
string ping = Encoding.ASCII.GetString(recData);
if (ping == "ping")
{
Console.WriteLine("Ping received.");
Console.WriteLine("Ping was sent from " + anyIP.Address.ToString() +
" on their port number " + anyIP.Port.ToString());
InvokePingReceiveEvent();
}
}
}
http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.receive.aspx

Categories

Resources