Receive response to UDP multicast on same port - c#

I'm trying to send out a multicast packet then receive the response that comes back (there should only be one response.) I can send the packet, and wireshark shows the reply but my program never receives it. I've tried a few different things but this is the current state of my non-functioning code.
IPEndPoint epReceive = new IPEndPoint(IPAddress.Any, 5355);
IPEndPoint epSend = new IPEndPoint(IPAddress.Parse("224.0.0.252"), 5355);
UdpClient sendClient = new UdpClient();
sendClient.ExclusiveAddressUse = false;
sendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sendClient.Client.Bind(epReceive);
sendClient.Send(packet, packetLength, epSend);
byte[] buffer = sendClient.Receive(ref epReceive);
sendClient.Close();
This code just hangs on the sendClient.Receive() line. I realise this code is currently blocking and could/should be threaded, but for the purposes it's being used for it's not a concern.

Related

Multicast listener port in use

I am new to multicast programming. So far I can successfully send and receive multicast messages from two separate processes (a sender and a receiver). My problem is with the receiver...
ReceiverCode:
private static void ReceiveMulticastMessages()
{
var groupEndPoint = new IPEndPoint(IPAddress.Parse("238.8.8.8"), 23888);
var localEndPoint = new IPEndPoint(IPAddress.Any, 23888);
using (var udpClient = new UdpClient())
{
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(localEndPoint);
udpClient.JoinMulticastGroup(groupEndPoint.Address, localEndPoint.Address);
while (true)
{
var remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
var bytes = udpClient.Receive(ref remoteEndPoint);
var message = Encoding.ASCII.GetString(bytes);
Console.WriteLine(message);
}
}
}
The above code works as long as I specify port 23888 for the localEndPoint. If I change the local port number, no messages are received. I would prefer to set it to 0 so the OS could choose the port. Why can I not specify a different local port than that of multicast group?
Assuming the local endpoint port must match the multicast group port, how does a client deal with a local port conflict?
On the flip side, how can an application (a multicast sender) choose a multicast group port such that any subscribers will not have a port conflict?
When sending any UDP message (not just muticast messages), the port that the sender sends to must match the port that the receiver is listening on. That's how messages get to the right place. If a message is sent to a port other that the one the receiver is bound to, the receiver won't get it.
So a port number needs to be defined that the receiver(s) will listen on and the server will send to.

C# Using tcp and udp protocols

I need to use udp and tcp connections in my application,the TcpClient/TcpListener would rarely be active,but the udp one would be the main usage.
This is the server code:
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 25655);
listener.Start();
Socket sck = listener.AcceptTcpClient().Client;
UdpClient udpServer = new UdpClient(1100);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
var data = udpServer.Receive(ref remoteEP);
string result = Encoding.UTF8.GetString(data);
Console.WriteLine(result);
Console.Read();
}
And this is the Client:
static void Main(string[] args)
{
TcpClient client = new TcpClient("127.0.0.1", 25655);
Socket sck = client.Client;
UdpClient udpclient = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1100); // endpoint where server is listening
udpclient.Connect(ep);
byte[] data = UTF8Encoding.UTF8.GetBytes("Hello");
udpclient.Send(data,data.Length);
}
I'm establishing the Tcp connection at first,then i'm trying to connect and send data from the client to the server.
From a breakpoint i add, i can see that the Tcp part works properly,the client finishes the program but in the server,it's hangs on the receiving part var data = udpServer.Receive(ref remoteEP);
like no data arrived..when i remove the tcp code part(the first 2 lines from the server and the client) it works great,shows the result message.
Does anyone know why im unable to get the data from the client?
Thanks in advance.
The main difference between UDP and TCP is that TCP is going to try to resend the message until the server tells the client it has received it. UDP is going to send and forget it even if the packet never reach or the host doesn't exist at all
Here is the flow of your code
Server starts up TCP
Client sends TCP
Server Receives TCP
Client sends UDP (server did not listen yet, packet lost but UDP doesn't care)
Server starts to listen to UDP
Server waiting for UDP to come <--- hang
You would like to do some multithread programming and start both of them at the same time before you tries to send message from the client.
The thing is that listener.AcceptTcpClient() blocks your current thread and UdpClient on server side is not established before Tcp connection created. In fact, your server is waiting for Tcp connection and only after that starting listening of Udp connections, while your client creates 2 connections one by one. My suggestions is - your server starting listening Udp port after the moment client actually sent data. The easiest way to check my suggestions - for client code add Thread.Sleep(1000) before sending data via UDP. In order to make that working you probably need to modify your code not blocking main thread but separate Tcp and Udp in the way similar to this:
static void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
TcpListener listener = new TcpListener(IPAddress.Any, 25655);
listener.Start();
Socket sck = listener.AcceptTcpClient().Client;
// ToDo: further actions related to TCP client
}, TaskCreationOptions.LongRunning);
UdpClient udpServer = new UdpClient(1100);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
var data = udpServer.Receive(ref remoteEP);
string result = Encoding.UTF8.GetString(data);
Console.WriteLine(result);
Console.Read();
}
client code can probably stay as it is for this example, but for real project I would recommend to separate that as well, as for sure you would like to get back some data from server via Tcp.
What if you first start the UDP client on server side and then establish the TCP connection between client and server?!
Server
static void Main(string[] args)
{
UdpClient udpServer = new UdpClient(1100);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
TcpListener listener = new TcpListener(IPAddress.Any, 25655);
listener.Start();
Socket sck = listener.AcceptTcpClient().Client;
var data = udpServer.Receive(ref remoteEP);
string result = Encoding.UTF8.GetString(data);
Console.WriteLine(result);
Console.Read();
}
Client
static void Main(string[] args)
{
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 25655);
UdpClient udpclient = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1100); // endpoint where server is listening
udpclient.Connect(ep);
byte[] data = UTF8Encoding.UTF8.GetBytes("Hello");
udpclient.Send(data, data.Length);
}

Reopen Tcp socket on the same port

I have a socket that serves a single request-response purpose.
I set it up on port XXX let it wait for a connection, read the data and reply with some data.
I would like to open a new socket on the same port. As soon as the response was sent.
That is handled externally (there is a manager that is checking the state of the thread and if it was used it disposes it and creates a new one.
The problem is that it gets blocked on
_socket = _socket.Accept();
and when a new client tries to connect it never leaves this line. (And client gets no reply).
The socket is running in
new Thread(Run);
and here is my Run method:
private void Run()
{
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, Port);
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
_socket = _socket.Accept();
var data = string.Empty;
while (true)
{
var bytes = new byte[1024];
var bytesRec = _socket.Receive(bytes);
data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>", StringComparison.Ordinal) <= -1) continue;
var dataWithoutEof = data.Substring(0, data.IndexOf("<EOF>", StringComparison.Ordinal));
//TODO: do smt with the data
break;
}
var byteData = Encoding.UTF8.GetBytes("testResponse" + "<EOF>");
_socket.Send(byteData);
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
I suppose that I am not closing the existing socket correctly.
You code is wrong you should not expect this method to exit because you want your server up and running the whole time. I am assuming here you call run several times. Don't do that.
The code becomes then something like this :
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
while (true)
{
var _servicingsocket = _socket.Accept();
....
_servicingsocket.close();
}
accept is a blocking call. That waits for a new connection.
_socket is a listening socket and must be kept during the lifetime of the server.
A TCP connection is based on the notion of a socket pair.
When the server starts you have a single socket that listens on port 100.
Suppose a connection is established, then accept returns what is called a servicing socket that is basically a clone from the listening socket. This means that it is also using source port 100, but because it is a servicing socket it belongs to a socket pair that identifies the connection. A socket pair is the combination of 2 sockets, your own socket and the peer. When a data comes in, TCP will iterate through the socket pairs to find the right socket.
An additional advantage of doing it this way is that you allow other connection attempts to queue up on the listening socket while you are processing the first request. Your _socket is overwritten with the servicing socket and you are then assuming that the listening socket is going to be garbage collected. I am not sure if this is going to happen because I haven't tried it like you are doing it in your code because it is a bad idea in the first place because it implements idisposable. (https://msdn.microsoft.com/en-us/library/system.net.sockets.socket%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) If you really want to close the server you have to make sure to close both the servicing socket and the listening socket to make the code clean.

C#. UDP unicast

I try to receive six messages from UDP unicast clients. Receiver looks like:
UdpClient udpclient = new UdpClient();
IPEndPoint localEp = new IPEndPoint(IPAddress.Parse(ClientIP), ClientPort);
udpclient.Client.Bind(localEp);
udpclient.Client.ReceiveTimeout = 10000;
bool isTimeExpired = false;
while (!isTimeExpired)
{
byte[] buffer;
try
{
buffer = udpclient.Receive(ref localEp);
}
catch (SocketException)
{
isTimeExpired = true;
continue;
}
// Deserialize
// ...
}
udpclient.Close();
Program works, but sometimes I don't receive 6 messages (2 or 3). Sender application:
UdpClient client = new UdpClient();
IPEndPoint remoteep = new IPEndPoint(IPAddress.Parse(ClientIP), ClientPort);
// Serialize
// ...
stream.Position = 0;
byte[] data = new Byte[stream.Length];
stream.Read(data, 0, Convert.ToInt32(stream.Length));
client.Send(data, data.Length, remoteep);
stream.Close();
client.Close();
I run 6 instances of sender application at the same machine (and one instance of receiver). I need to receive messages from every sender (six messages total) all the time. Where is my mistake?
Thank you very much!
It's UDP. There's no guarantee you'd receive any of the datagrams that were sent. UDP is, by design, unreliable. The "User" in the UDP might as well stand for "Unreliable" instead. :)
FYI: there also is no guarantee that you'll receive only one copy of any given datagram that was sent. There is also no guarantee that the datagrams will arrive in the same order in which they were sent.
If you need that kind of reliability, then you need TCP, not UDP (or you need to do a bunch of extra work to re-invent the TCP wheel).

How do I reuse a TCP endpoint address with .Net sockets

I have some client-server socket code that I want to be able to construct and (re)connect to periodically the same endpoint address: localhost:17999
Here is the server:
// Listen for a connection:
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Loopback, 17999);
Socket listener = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
listener.Bind(localEndPoint);
listener.Listen(1);
// Accept the connection and send a message:
Socket handler = listener.Accept();
byte[] bytes = new byte[1024];
bytes = Encoding.ASCII.GetBytes("The Message...");
handler.Send(bytes);
// Clean up
handler.Shutdown(SocketShutdown.Both);
handler.Close();
handler.Dispose();
listener.Shutdown(SocketShutdown.Both);
listener.Close();
listener.Dispose();
And here is the client:
byte[] bytes = new byte[1024];
Socket receiver = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
receiver.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receiver.Connect(new IPEndPoint(IPAddress.Loopback, 17999));
int num_bytes_received = receiver.Receive(bytes);
string result = Encoding.ASCII.GetString(bytes, 0, num_bytes_received);
receiver.Shutdown(SocketShutdown.Both);
receiver.Close();
receiver.Dispose();
When I create the client and server for the first time, it works fine. However when I create it again, I get an error:
"A request to send or receive data was disallowed because the socket is
not conne cted and (when sending on a datagram socket using a sendto
call) no address was supplied"
I would like to be able to spin up this mechanism arbitrarily whenever I need to with the following order of events:
Launch the server and wait to accept a connection
Launch the client and connect to the server
Accept the client connection at the server
Send a message to the client
Repeat when necessary
How can I do this?
Thx in Advance!
EDIT: Each time I build the client and server objects it is from a different process.
You have two issues:
1) You're closing the listener. Just leave it open.
2) You're setting ReuseAddress on the wrong socket and way too late. Set it on the listening socket before you call bind (since that's when you use the address).
Setting ReuseAddress on a socket you aren't going to bind doesn't do anything. You can remove that from the client.
I tried what Gene suggested and it seems to work:
// Listen for a connection:
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Loopback, 17999);
using (Socket listener = new Socket(IPAddress.Loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
listener.Bind(localEndPoint);
listener.Listen(1);
Thread t = new Thread(() =>
{
// Accept the connection and send a message:
using (Socket handler = listener.Accept())
{
byte[] bytes = new byte[1024];
bytes = Encoding.ASCII.GetBytes("The Message...");
handler.Send(bytes);
}
});
t.Start();
t.Join();
}
Thanks, all!

Categories

Resources