I'm trying to send a UDP command to a device and receive a UDP response from that same device. The sending works fine. I can see the datagram depart (via WireShark). I can also see the datagram return from the device (again, via WireShark). The turnaround time between command departure and response reception is about 15 milliseconds.
Code
Byte[] button_click(Byte[] command)
{
// Device exists at a particular IP address and listens for UDP commands on a particular port
IPEndPoint SendingEndpoint = new IPEndPoint(DEVICE_IP, DEVICE_PORT);
// Device always sends from port 32795 to whatever port the command originated from on my machine
IPEndPoint ReceivingEndpoint = new IPEndPoint(DEVICE_IP, 32795);
// Sending client
sendingClient = new UdpClient();
sendingClient.Connect(SendingEndpoint);
// Receiving client
receivingClient = new UdpClient();
receivingClient.Client.ReceiveTimeout = RECEIVE_TIMEOUT; // timeout after 4 seconds
receivingClient.Connect(receivingEndpoint);
// Send command and wait for response
Byte[] response = null;
try
{
sendingClient.Connect(DEVICE_IP, DEVICE_PORT);
sendingClient.Send(command, command.Length);
response = receivingClient.Receive(ref receivingEndpoint);
}
catch (SocketException e)
{
// If we timeout, discard SocketException and return null response
}
return response;
}
Problem
I cannot capture the received datagram in my application. When I run the above code, I get the following exception:
"A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond."
There are similar posts on StackOverflow, but none of them appear to address my situation. And I've verified that my packets are not being swept up in my firewall.
What am I doing wrong?
I solved the problem. The solution required two things:
The sending and receiving clients had to use the same local port
The sending client had to use an IPEndPoint declared with IPAddress.Any and the receiving client had to use an IPEndPoint declared with the exact IP address of my local machine
Code
// Create endpoints
IPEndPoint DeviceEndPoint = new IPEndPoint(DEVICE_IP, DEVICE_PORT);
IPEndPoint localEndPointAny = new IPEndPoint(IPAddress.Any, LOCAL_PORT); // helps satisfy point 2
IPEndPoint localEndPointExplicit = new IPEndPoint(IPAddress.Parse(GetLocalIPAddress()), LOCAL_PORT); // helps satisfy point 2
IPEndPoint incomingEndPoint = null; // Later populated with remote sender's info
// Create sending client
UdpClient sendingClient = new UdpClient();
sendingClient.ExclusiveAddressUse = false; // Going to use same port for outgoing and incoming (helps satisfy point 1)
sendingClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // helps satisfy point 1
sendingClient.Client.Bind(localEndPointAny); // Any outgoing IP address will do
// Create receiving client
UdpClient receivingClient = new UdpClient();
receivingClient.Client.ReceiveTimeout = RECEIVE_TIMEOUT; // 4000 milliseconds
receivingClient.ExclusiveAddressUse = false; // Going to use same port for outgoing and incoming (helps satisfy point 1)
receivingClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // helps satisfy point 1
receivingClient.Client.Bind(localEndPointExplicit); // Must explicitly give machine's outgoing IP address
The code for getting a local IP address can be found here.
If you use the sendingClient to receive, then you can get the proper message. The reason is that the IP is consisted of Host+Port+Protocol, when the sending point connect to the device and send the message, the device receive the Endpoint and the UDP paired with the sending Endpoint. When receive client try to receive the message, there is nothing happen since UDP is Peer to Peer, and the receive client's port must be different to the send client, as a result, receive client get nothing. The following is my sample code for your reference.
IPAddress address;
IPAddress.TryParse("127.0.0.1", out address);
IPEndPoint recPoint = new IPEndPoint(address, 13154);
// IPEndPoint sendPoint = new IPEndPoint(address, 9999);
UdpClient send = new UdpClient(9999);
send.Connect(recPoint);
Byte[] response = null;
Byte[] command = System.Text.Encoding.Default.GetBytes("NO one");
try
{
send.Send(command, command.Length);
response = send.Receive(ref recPoint);
}
catch(Exception ex) {
Console.WriteLine(ex.ToString());
}
According to Alex's answer, I update a full example code for reference.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Net;
namespace console
{
class Program
{
static void Main(string[] args)
{
IPAddress address;
IPAddress.TryParse("192.168.14.173", out address);
IPEndPoint recPoint = new IPEndPoint(address, 13154);
IPEndPoint recAnyPoint = new IPEndPoint(IPAddress.Any, 13154);
IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("192.168.14.174"), 13154);
// IPEndPoint sendPoint = new IPEndPoint(address, 9999);
UdpClient send = new UdpClient();
send.ExclusiveAddressUse = false;
// no need to use the low level socketoption
// send.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
send.Client.Bind(recAnyPoint);
send.Connect(ipPoint);
UdpClient receive = new UdpClient();
receive.ExclusiveAddressUse = false;
// receive.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receive.Client.Bind(recPoint);
receive.Connect(ipPoint);
Byte[] response = null;
Byte[] command = System.Text.Encoding.Default.GetBytes("NO one");
try
{
send.Send(command, command.Length);
response = receive.Receive(ref ipPoint);
Console.WriteLine(System.Text.Encoding.Default.GetString(response));
}
catch(Exception ex) {
Console.WriteLine(ex.ToString());
}
}
}
}
Related
I'm writing a very simple .NET TCP Server and very simple TCP Client that should both run on the same machine (Window 10 Home PC) and connect each other (for testing purposes only).
In the server I'm waiting for the connection in this way:
public static void StartListening()
{
string hostname = Dns.GetHostName();
IPHostEntry ipHostInfo = Dns.GetHostEntry(hostname);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Properties.Settings.Default.Port);
Socket listener = new Socket(
ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(Properties.Settings.Default.Port);
while (true)
{
allDone.Reset();
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
var frames = Directory.EnumerateFiles(Properties.Settings.Default.FramesPath);
foreach (string filename in frames)
{
Console.Write("Sending frame: {}...", filename);
SendFile(handler, filename);
Thread.Sleep(Properties.Settings.Default.FrameDelay);
}
}
In the client I'm creating a connection in this way:
private void startClient(string host, int port)
{
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port);
ClientTCP = new TcpClient();
ClientTCP.Connect(serverEndPoint);
Reader = new StreamReader(ClientTCP.GetStream());
Listen = true;
listner = Listener();
}
startClient is called in this way.
startClient(txtAddr.Text, (int)int.Parse(txtPort.Text));
When I run the client setting host variable to the current machine name (the same the server retrieve trough Dns.GetHostName() I got this exception:
An invalid ip address was specified.
I tried using 127.0.0.1 and I got:
Connection could not be established. Persistent rejection of the target computer 127.0.0.1:5002
I tried with localhost and I got
An invalid ip address was specified
again. I tried with the IP address assigned to WiFi and I got again
Connection could not be established. Persistent rejection of the target computer 192.168.10.11:5002
I'm sure the computer network works since I'm using it for many other things including connecting to local TCP services and I'm sure both client and server code works since on a different PC I'm able to connect them setting localhost as client host variable value. Why I'm unable to use loopback connections in my code?
Where did I fail?
P.S. I allowed connection to server binary in Windows firewall rules, I also allowed outgoing connection for client binary also.
For anyone willing to inspect the server code here it is:
Server code
You are using the constructor with the "IPEndPoint" parameter. This constructor does not connect to the server automatically and you must call the "Connect" method before using the socket. That is why you are getting the error message "Operation not allowed on unconnected sockets". Also, you have provided a wrong IPEndPoint for client.
Please try this on client:
private void startClient(string host, int port)
{
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port);
ClientTCP = new TcpClient();
ClientTCP.Connect(serverEndPoint);
Reader = new StreamReader(ClientTCP.GetStream());
Listen = true;
listner = Listener();
}
You may need some exception handling here, but it should work now.
UPDATE:
The ipHostInfo.AddressList may have more than one addresses and just one of them is what you wanted. It is not necessarily the first one. I specified this manually and it works:
//string hostname = Dns.GetHostName();
//IPHostEntry ipHostInfo = Dns.GetHostEntry("127.0.0.1");
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5002);
I spend hours trying to implement Hole punching in C# , my project need a connection to be made directly between me ( server ) and other slaves (peers) , I have third party server that I'm using to keep track external IPs which belongs to the server and peers .
the Code I managed to write until now works fine when I supply an internal IP for the server ( loopback or (0.0.0.0)) but it don't when I put my external ip .. it give no exceptions , but when using a tool like packet sender to test it , the server recieve the datagram just from the loopback , not my external .
here my Server implementation :
class Program
{
static byte[] dataToSend = Encoding.ASCII.GetBytes("Test");
// get the ip and port number where the client will be listening on
static IPEndPoint GetClientInfo()
{
// wait for client to send data
using (UdpClient listener = new UdpClient(11000))
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("188.247.78.18") , 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);
return groupEP;
}
}
static void Main(string[] args)
{
var info = GetClientInfo(); // get client info
/* NOW THAT WE HAVE THE INFO FROM THE CLIENT WE ARE GONG TO SEND
DATA TO IT FROM SCRATCH!. NOTE THE CLIENT IS BEHIND A NAT AND
WE WILL STILL BE ABLE TO SEND PACKAGES TO IT
*/
// create a new client. this client will be created on a
// different computer when I do readl udp punch holing
UdpClient newClient = ConstructUdpClient(info);
Console.WriteLine(info.Address.ToString());
// send data
newClient.Send(dataToSend, dataToSend.Length);
Console.ReadKey();
}
// Construct a socket with the info received from the client
static UdpClient ConstructUdpClient(IPEndPoint clientInfo)
{
var ip = clientInfo.Address.ToString();
var port = clientInfo.Port;
// this is the part I was missing!!!!
// the local end point must match. this should be the ip this computer is listening on
// and also the port
UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 11000));
// lastly we are missing to set the end points. (ip and port client is listening on)
// the connect method sets the remote endpoints
client.Connect(ip, port);
return client;
}
}
and this is my Client implementation :
class Program
{
static void Main(string[] args)
{
string ipOfServer = "188.247.78.18"; //this is my external Ip and it doesn't work giving me nothing in the server Console ( but if I replaced it with 127.0.0.1 server console response)
int portServerIsListeningOn = 11000;
// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- we can receive data now!!!!!
}
}
how to make this works , and how to test it to make sure that the server working in my pc from outside ?
I'm writing application which is based on UDP Hole Punching. I have a problem with establishing connection between clients. After each client sends something to server and server responses to each other with their IPs, clients aren't able to send anything to each other. Am I missing anything? Or my understanding of UDP Hole Punching is wrong? Yes, I've external IP for PC where server is.
server code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
IPAddress IP = IPAddress.Parse("xx.xx.xx.xxx");
IPEndPoint localEP = new IPEndPoint(IP, 80);
UdpClient server = new UdpClient();
server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
server.ExclusiveAddressUse = false;
server.Client.Bind(localEP);
IPEndPoint temp;
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 80);
Console.WriteLine("Dane servera : " + localEP);
byte[] buffer = server.Receive(ref remoteEP);
Console.WriteLine("Otrzymano dane od : " + remoteEP + " o treści " + Encoding.ASCII.GetString(buffer));
temp = remoteEP;
remoteEP = new IPEndPoint(IPAddress.Any, 80);
byte[] buffer2 = server.Receive(ref remoteEP);
Console.WriteLine("Otrzymano dane od : " + remoteEP + " o treści " + Encoding.ASCII.GetString(buffer2));
byte[] response = Encoding.ASCII.GetBytes(temp.ToString());
server.Send(response, response.Length, remoteEP);
byte[] response2 = Encoding.ASCII.GetBytes(remoteEP.ToString());
server.Send(response2, response2.Length,temp );
}
}
}
client 1:
namespace ConsoleApplication1
{
class Program
{
public static IPEndPoint CreateIPEndPoint(string endPoint)
{
string[] ep = endPoint.Split(':');
if (ep.Length < 2) throw new FormatException("Invalid endpoint format");
IPAddress ip;
if (ep.Length > 2)
{
if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
else
{
if (!IPAddress.TryParse(ep[0], out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
int port;
if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port))
{
throw new FormatException("Invalid port");
}
return new IPEndPoint(ip, port);
}
static void Main(string[] args)
{
IPAddress IP = IPAddress.Parse("xx.xx.xx.xxx");
IPEndPoint localpt = new IPEndPoint(IP, 80);
UdpClient client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
string powitanie = "ASUS";
byte[] buffer = new byte[100];
buffer = Encoding.ASCII.GetBytes(powitanie);
// client.Connect(localpt);
client.Send(buffer, buffer.Length,localpt);
byte[] otrzymane = client.Receive(ref localpt);
Console.WriteLine("Odpowiedz servera : " + Encoding.ASCII.GetString(otrzymane));
Console.Read();
IPEndPoint TV = CreateIPEndPoint(Encoding.ASCII.GetString(otrzymane));
byte[] buffer2 = client.Receive(ref TV);
Console.WriteLine("Odpowiedz klienta : " + Encoding.ASCII.GetString(buffer2));
}
}
}
client 2:
namespace ConsoleApplication1
{
class Program
{
public static IPEndPoint CreateIPEndPoint(string endPoint)
{
string[] ep = endPoint.Split(':');
if (ep.Length < 2) throw new FormatException("Invalid endpoint format");
IPAddress ip;
if (ep.Length > 2)
{
if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
else
{
if (!IPAddress.TryParse(ep[0], out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
int port;
if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port))
{
throw new FormatException("Invalid port");
}
return new IPEndPoint(ip, port);
}
static void Main(string[] args)
{
IPAddress IP = IPAddress.Parse("xx.xx.xx.xxx");
IPEndPoint localpt = new IPEndPoint(IP, 80);
UdpClient client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
string powitanie = "Samsung";
byte[] buffer = new byte[100];
buffer = Encoding.ASCII.GetBytes(powitanie);
// client.Connect(localpt);
client.Send(buffer, buffer.Length,localpt);
byte[] otrzymane = client.Receive(ref localpt);
Console.WriteLine("Odpowiedz servera : " + Encoding.ASCII.GetString(otrzymane));
Console.Read();
IPEndPoint TV = CreateIPEndPoint(Encoding.ASCII.GetString(otrzymane));
client.Send(buffer, buffer.Length, TV);
}
}
}
Without access to your exact environment and network, I am not convinced it will be possible to offer an answer with any confidence that it would be assured of addressing the issue. But here are something things to keep in mind:
First and foremost, "hole punching" is not a well-defined feature with a technical specification or industry standard for support. There is never any guarantee that it will work, though of course many routers work in a way that allows it to. If you are sure your code is correct but is for some reason still not working, it is always possible that you are using one or more routers that simply won't work with the technique.
Depending on the router behavior, it may or may not be sufficient for a client to have sent a datagram from a specific endpoint. A router may not route foreign datagrams to that endpoint until the recipient of the original outbound datagram has replied, i.e. two-way communication has in fact been established. Your current implementation appears to include code to allow the user testing the code to wait for both server replies before attempting to send to the other client, but do make sure you're taking advantage of that. I.e. that you don't try to send from one client to the other until both clients have received the server response.
In addition to the above, it may not be sufficient for the server to have sent datagrams to each client. A router may still discard datagrams received from an unknown endpoint. So a variation on the technique that is often required is that one client attempts to send a datagram to the other client, but also notifies that client via the server that it has done so (i.e. sends the server a datagram reporting this, and then the server sends a datagram to the intended recipient client to notify it).This datagram will be discarded, but the sending client's router doesn't know this, so when the other client replies directly to the sending client (having been notified by the server that it should), now the original sending client's router will pass the datagram to the that client. It saw the previous datagram that was intended for that other client, so it treats the inbound datagram from that other client as valid. From that point forward, both clients should be able to send to each other directly. Naturally, implementing this requires a more complicated application protocol than just forwarding IP addresses as your example here does.
Your code examples use SocketOptionName.ReuseAddress, which is almost always wrong. It appears to me that only your server socket binds to an explicit address, so using this option probably wouldn't affect the outcome of the test (i.e. you still only have one socket on any given address, even if you are testing in a single machine). But if there is more to your testing environment, such that the socket address really is being reused, that can easily interfere with the correct operation of the code.
Finally, you ask in a comment (please put relevant information and questions in the question itself): "should I use udp.connect to the server and then udp.send between clients". The answer is "no". First of all, using Connect() on a UDP socket is merely a convenience; UDP itself is connectionless, and so connecting a UDP socket is handled entirely within the framework. Second, in .NET when you "connect" a UDP socket, the framework will filter datagrams, restricting them to those received from the "connected" endpoint. This is exactly the opposite of what you want with hole-punching; i.e. you want to be able to receive datagrams from both the server and the other client.
I am working on the application which send and receive messages on UDP between client app and server app.
On my server I have 4 different network cards, e.g. nic1 = 169.524.15.12, nic2 = 169.524.15.65, etc. My DNS is point to nic2. The client app resolves the DNS and send data to nic2. However my server app sometime respond to client from nic1.
I'm using an UdpClient to listen for incoming packets.
This is my server application code:
objSocketServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint objEndPointOfServer = new IPEndPoint(IPAddress.Any, 5000);
objSocketServer.Bind(objEndPointOfServer);
objSocketServer.BeginReceiveFrom(_arrReceivedDataBuffer, 0, BUFSIZE - 1, SocketFlags.None, ref objEndPointOfServer, DoReceiveFromClient, objSocketServer);
private void DoReceiveFromClient(IAsyncResult objIAsyncResult)
{
try
{
// Get the received message.
_objSocketReceivedClient = (Socket)objIAsyncResult.AsyncState;
EndPoint objEndPointReceivedClient = new IPEndPoint(IPAddress.Any, 0);
// Received data.
int intMsgLen = _objSocketReceivedClient.EndReceiveFrom(objIAsyncResult, ref objEndPointReceivedClient);
byte[] arrReceivedMsg = new byte[intMsgLen];
Array.Copy(_arrReceivedDataBuffer, arrReceivedMsg, intMsgLen);
// Client port.
// Get and store port allocated to server1 while making request from client to server.
int _intClientServer1Port = ((IPEndPoint)objEndPointReceivedClient).Port;
// Send external ip and external port back to client.
String strMessage = ((IPEndPoint)objEndPointReceivedClient).Address.ToString() + ":" + _intClientServer1Port.ToString();
byte[] arrData = Encoding.ASCII.GetBytes(strMessage);
objSocketServer.SendTo(arrData, arrData.Length, SocketFlags.None, objEndPointReceivedClient);
// Start listening for a new message.
EndPoint objEndPointNewReceivedClient = new IPEndPoint(IPAddress.Any, 0);
objSocketServer.BeginReceiveFrom(_arrReceivedDataBuffer, 0, _arrReceivedDataBuffer.Length, SocketFlags.None, ref objEndPointNewReceivedClient, DoReceiveFromClient, objSocketServer)
}
catch (SocketException sx)
{
objSocketServer.Shutdown(SocketShutdown.Both);
objSocketServer.Close();
}
}
}
Is there any way so that in code, I can detect that I have received packet on which IP address on server and revert with the response with same IP?
Arguably, I could resolve DNS in server app as well and make sure that my server app only listen to IP on which client app is sending packets, however that approach will not work for me when my server app have to listen on > 1 IP.
The SendTo command will use the appropriate NIC (aka, local interface) for the destination address provided. The system metrics determine that. It's not something you set in your code. To view the system metrics, run the command netstat -rn and look at the Interface column. You many need to adjust those if you have a tie. You can enumerate them in code as well using GetAllNetworkInterfaces() and bind to a specific one (if that is what you wanted).
I am currently using this function to send data from the server to the clients
private static void send_message(string ip, string message)
{
byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(message);
int port = 11000;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SendTo(packetData, ep);
}
But this would mean a destination IP/port can only have one client open to receive the data, because having two clients open would mean one client can retrieve data that was meant for another (if I'm correct).. how do I solve this?
Receiving function:
private static Int32 port = 11000;
private static UdpClient udpClient = new UdpClient(port);
public static void receive_threaded()
{
Thread t = new Thread(() =>
{
while (true)
{
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port);
byte[] content = udpClient.Receive(ref remoteIPEndPoint);
if (content.Length > 0)
{
string message = Encoding.UTF8.GetString(content);
parseMessage(message);
}
}
});
t.Start();
}
1) You should implement some kind of protocol so that your server has a "well known" port to accept connections. Use this port to inform your client ANOTHER port where the client must connect. Use a different port for each client.
Your client conects to the server at 11000. Your server assigns a unique port for the client, let's say 11001 for the firts client. Then the server opens a connection at 11001. The client closes connection at 11000 and opens a new connection at 11001 to receive the data.
2) Why UDP?
I don't see why you need to open a new socket at all. You already have each client's address and port, from the first packet they sent you. Just send a packet to that address:port. I absolutely don't get the other suggestion of setting up extra ports either.