Hello I am developing sample application for demonstration of udp client to send data from client to server. I have created console application and below is my code.
class Program
{
static void Main(string[] args)
{
senddata();
while (true)
{
try {
UdpClient udpClient = new UdpClient(9999);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
string result;
result = returnData.ToString();
}
catch(Exception e)
{
}
}
void senddata()
{
UdpClient udpClient = new UdpClient(9999);
udpClient.Connect("10.170.84.163", 9999);
Byte[] senddata1 = Encoding.ASCII.GetBytes("Hello World");
udpClient.Send(senddata1, senddata1.Length);
}
}
}
whenever Byte[] receiveBytes is executed i get my empty black screen and nothing is going to happen. Can someone tell me how to fix this? Any help would be appreciated. Thank you.
There are several issues here:
You send data to udp port (via senddata()) before starting a listener on that port, and you do this only once, so there is no chance listener might receive it.
There is no need to bind UdpClient to specific port when sending data, especially to the same port on which you are listening with another UdpClient. Just use UdpClient udpClient = new UdpClient(); to let it use any available port for sending.
Since you are testing - there is no need to send data to your external ip, send to loopback interface instead: udpClient.Connect(IPAddress.Loopback, 9999);.
UdpClient implements IDisposable, so dispose it when you are done.
Your while (true) loop will not work, because you don't dispose UdpClient, so on second iteration of the loop, second UdpClient will try to bind to the same 9999 port and fail, because there is already listener (which you didn't dispose) on that same port.
Your code with fixes above (obviously that is not "production" code so I won't add things like cancellation and so on, only fixes to be able to see message is coming):
static void senddata() {
// send message every 100 ms
while (true) {
// wrap in using
using (UdpClient udpClient = new UdpClient()) {
// loopback
udpClient.Connect(IPAddress.Loopback, 9999);
Byte[] senddata1 = Encoding.ASCII.GetBytes("Hello World");
udpClient.Send(senddata1, senddata1.Length);
}
Thread.Sleep(100);
}
}
static void Main(string[] args) {
// run sending in background
Task.Run(() => senddata());
try {
// wrap in using
using (UdpClient udpClient = new UdpClient(9999)) {
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
// move while loop here
while (true) {
// this blocks until message is received
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
}
}
catch (Exception e) {
// do something meaningful
}
}
It doesn't look like you're outputting the received string.
Something like this....
string result;
result = returnData.ToString();
Console.WriteLine(result);
Try changing the following:
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
To use the port 9999 rather than a random port. I'm honestly somewhat surprised that doesn't throw an exception.
Note that binding to a random port as a server is not atypical but the remote end will need some way to discover that random port I..E. the way ftp uses a second port for actual file data transfer, that port number is sent as part of the message starting the transfer.
Related
I've made a simple chat application in c#.net that sends and receives data between 2 computers.
So, I used this method to send the data:
int port = 11000;
private void send(string data, string ip)
{
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint sending_end_point = null;
byte[] send_buffer = Encoding.ASCII.GetBytes(data);
sending_end_point = new IPEndPoint(IPAddress.Parse(ip), port);
try { sending_socket.SendTo(send_buffer, sending_end_point); }
catch { }
}
And to receive I used this:
string receiveddata = "";
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
UdpClient listener = new UdpClient(port);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, port);
byte[] receive_byte_array;
try
{
receive_byte_array = listener.Receive(ref groupEP);
receiveddata = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
}
catch { }
listener.Close();
}
This works without any problems between 2 computers on a LAN, but I would like to know (if possible) how to do the same thing over the Internet.
From what I've searched on the Internet, it seems that I have to use port-forwarding in order to do that, so I already did that, but I don't know what should I do know.
So my question is, how should I change this code (if I have to) so I could send and receive data (UDP) over the internet, assuming I have port-forwarded correctly already and assuming I know the external IPs of both routers?
Thank you in advance.
This should work just fine, as long as your (public) IP-address is correct and the ports are forwarded correctly on your router (meaning, forwarded to the correct private IP, on the correct protocol, in your case UDP).
You are aware that this is UDP though, so it's not reliable data transfer.
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).
I am using UdpClient class in .net 3.5
I need to bind multiple applications to the same port .
So, if UDP servers broadcast any request - all the applications thats listen on the port can receive the message but the problem is, when I try bind to an application to the same port, only one application receive the message and the other does not.
Below is some sample code for the two application:
UdpClient udpClient = new UdpClient();
Thread thread;
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 11000);
public Form1()
{
//CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(
SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(endPoint);
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
thread.Abort();
udpClient.Close();
Close();
}
}
private void ReceiveMessage()
{
//while (true)
//{
// IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 11000);
// byte[] content = udpClient.Receive(ref endPoint);
udpClient.BeginReceive(new AsyncCallback(Read_Callback), null);
//if (content.Length > 0)
//{
// string message = Encoding.ASCII.GetString(content);
// this.Invoke(myDelegate, new object[] { message });
//}
// }
}
public void Read_Callback(IAsyncResult ar)
{
try
{
byte[] buffer = udpClient.EndReceive(ar, ref endPoint);
// Process buffer
string s = Encoding.ASCII.GetString(buffer);
// richTextBox1.Text = s;
udpClient.BeginReceive(new AsyncCallback(Read_Callback), null);
}
catch (Exception ex)
{ }
}
PS : I am unable to figure out the reason or am I missing something. ?
That's the nature of sockets. Even in cases (such as UDP) where multiple applications can access the same port, the data is handed out first-come, first-serve. UDP is also designed with minimum overhead, so there isn't even an opportunity to "check the queue," like you (hypothetically) could with TCP.
It's designed around having multiple processes share a server load, alternating who receives the request based on who's idle.
You'd need to build something external to get around this, like a retransmission protocol or a database to make sure every inbound message is shared.
If you can deal with the changes, a smarter way to handle this would be UDP Multicast, where multiple programs essentially enroll to receive group messages. In that case, the single-port restriction can (and should) be abandoned.
I am just starting out Socket Programming in C# and am now a bit stuck with this problem.
How do you handle multiple clients on a single server without creating a thread for each client?
The one thread for each client works fine when there are say 10 clients but if the client number goes up to a 1000 clients is creating a thread for every single one of them advisable? If there is any other method to do this can someone please tel me?
Try to use asynchronous server.
The following example program creates a server that receives connection requests from clients. The server is built with an asynchronous socket, so execution of the server application is not suspended while it waits for a connection from a client. The application receives a string from the client, displays the string on the console, and then echoes the string back to the client. The string from the client must contain the string <EOF> to signal the end of the message.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
public class StateObject {
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener {
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener() {
}
public static void StartListening() {
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// 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(100);
while (true) {
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener );
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args) {
StartListening();
return 0;
}
}
That's will be the best solution.
Threads can work fine but rarely scales well to that many clients. There are two easy ways and lots of more complex ways to handle that, here's some pseudocode for how the easier two are usually structured to give you an overview.
select()
This is a call to check which sockets have new clients or data waiting on them, a typical program looks something like this.
server = socket(), bind(), listen()
while(run)
status = select(server)
if has new client
newclient = server.accept()
handle add client
if has new data
read and handle data
Which means no threads are needed to handle multiple clients, but it doesn't really scale well either if handle data take a long time, then you won't read new data or accept new clients until that's done.
Async sockets
This is another way of handling sockets which is kind of abstracted above select. You just set up callbacks for common events and let the framework do the not-so-heavy lifting.
function handleNewClient() { do stuff and then beginReceive(handleNewData) }
function handleNewData() { do stuff and then beginReceive(handleNewData) }
server = create, bind, listen etc
server.beginAddNewClientHandler(handleNewClient)
server.start()
I think this should scale better if your data handling take a long time. What kind of data handling will you be doing?
This could be a good starting point. If you want to avoid 1 thread <-> 1 client; then you should use async socket facilities provided in .NET. Core object to use here is SocketAsyncEventArgs.
Im new to Sockets and C# in general and am having a difficult time implementing a simple upd listener function. I've spent alot of time searching the web tying unsuccessfully to intergate any of the numerious examples online. So any suggestions, links, examples would be greatly appreciated!
At this point, I have a third party application broadcasting over port 6600 a general UPD message containing information about the location of the application server (ServerName, IP Address, etc.). I'd like to design my listener client application to capture the UPD broadcast and generate a collection of the available servers which can be used to future processing.
The problem I'm having is that when I attempt to create the listener using listener.Listen(0) if fails and generates a general type error. If I attempt to us the UdpClient class my application hangs and never returns any data. The Code for both examples is listed below:
namespace UDPListener
{
class Program
{
static void Main(string[] args)
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
listener.Bind(new IPEndPoint(IPAddress.Any, 6600));
listener.Listen(6);
Socket socket = listener.Accept();
Stream netStream = new NetworkStream(socket);
StreamReader reader = new StreamReader(netStream);
string result = reader.ReadToEnd();
Console.WriteLine(result);
socket.Close();
listener.Close();
}
}
}
And the UdpClient:
private void IdentifyServer()
{
//Creates a UdpClient for reading incoming data.
UdpClient receivingUdpClient = new UdpClient(6600);
//Creates an IPEndPoint to record the IP Address and port number of the sender.
// The IPEndPoint will allow you to read datagrams sent from any source.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
try
{
// Blocks until a message returns on this socket from a remote host.
Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
Output.Text = ("This is the message you received " +
returnData.ToString());
Output.Text = ("This message was sent from " +
RemoteIpEndPoint.Address.ToString() +
" on their port number " +
RemoteIpEndPoint.Port.ToString());
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
dtb was absolutely write! After much research and some help from a friend I realized that what I was actually looking for was a solution for Multicasting. I'll include the links below.
#dtb, thanks for helping point me in the right direction!
http://www.codeproject.com/Articles/1705/IP-Multicasting-in-C
http://codeidol.com/csharp/csharp-network/IP-Multicasting/Csharp-IP-Multicast-Support/