I have a simple UDP listener that I am trying to collect datagrams from. My datagrams can be in one of two data formats. With the first data format, I am receiving data in my program as expected. With the second, there is absolutely no indication that data is ever received from my program, even though I can verify that the UDP data is passing onto the the network interface via Wireshark. I thought that maybe these were malformed UDP packets that Windows was rejecting but Wireshark does label them as UDP. My code is below:
static void Main(string[] args)
{
Thread thdUdpServer = new Thread(new ThreadStart(serverThread));
thdUdpServer.Start();
}
static void serverThread()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(new IPAddress(0), 2000));
while (true)
{
byte[] responseData = new byte[128];
socket.Receive(responseData);
string returnData = Encoding.ASCII.GetString(responseData);
Console.WriteLine(DateTime.Now + " " + returnData);
}
The missing packets are all 29 byte datagrams that look something like this (translated to ASCII).
#01RdFFFF...?...... ........F
Why would Wireshark indicate their presence but .NET not seem to see them?
If the bytes contain non-printable ASCII characters, you may not see them on the Console.
There's something missing in your code. It should be throwing a socket exception when calling ReceiveFrom (at least according to MSDN, haven't tried your code.)
You should bind your socket to the address:port you want to listen on (or use 0.0.0.0 as the address to listen on any local address):
socket.Bind(new IPEndPoint(new IPAddress(0), 2000);
The EndPoint in ReceiveFrom is not the listening port for the server. It's the address you want to receive packets from. You can use an Endpoint of 0.0.0.0:0 to receive from any host.
After returning from the method the Endpoint will be filled with the address of the host that sent the packet (client).
You can use Receive instead of ReceiveFrom if you don't care about the client end point.
Likely your client is not sending packets from 192.168.1.100:2000, and that is why you are not receiving them; thought why you're not getting an exception when calling ReceiveFrom is beyond me.
Also:
There is no need to call Convert.ToInt32 in:
new IPEndPoint(IPAddress.Parse("192.168.1.100"), Convert.ToInt32(2000));
2000 is already an int.
Related
I am trying to send multiple packets using TcpClient. this code works on the first iteration. but after the first iteration the server isn't receiving anything(although the loop keeps iterating). server-side code is working fine as I have been testing it with packet sender. Anything to send burst of packets using TcpClient?
TcpClient tcpClient = new TcpClient(localIpAddress,localPort);
tcpClient.NoDelay = true;
tcpClient.Connect(remoteIpAddress,remotePort);
Stream stream=tcpClient.GetStream();
int i = 0;
while (true)
{
i = i + 1;
Console.WriteLine("Message {0} Sent",i);
stream.Write(Encoding.ASCII.GetBytes(message))));
stream.Flush();
Thread.Sleep(500);
}
You can't accurately control sending of packets using TcpClient. In fact you can't even do it with a TCP Socket(). You'd need to use a Raw Socket and structure your own TCP packets.
The TCP stack decides when it's going to send a packet based on the socket configuration options, how much information is in the buffer, when the last ACK was, what the window size is, what the RTT is and a few other things.
You can fudge it, by sending lots of data, which will force the TCP stack to send them immediately as fast as it can. You can also set the TcpClient.NoDelay() but this will not work for multiple successive writes unless you have a reasonable delay between writes and even then it is not gauranteed.
You can make low level calls to work out how many packets were sent/recv, but you can only influence this by tweaking the parameters of the TCP stack and even then it will never be deterministic due to the fact the IP is a lossy protocol and TCP packets will go missing and need to be retransmitted.
Your problem with the code above is that you're setting a LocalEndPoint with this line:
TcpClient tcpClient = new TcpClient(localIpAddress,localPort);
The port will not be reusable until the Socket has passed through the TIME_WAIT phase which, depending on how the socket shutdown could be 120seconds.
Change that line to:
TcpClient tcpClient = new TcpClient();
Or if you must set the source IP address
TcpClient tcpClient = new TcpClient(localIpAddress,0);
You can read about the TIME_WAIT here and why it is an intrinsic part of the TCP Protocol.
As a side note, stream.Flush(); or NetworkStream.Flush() does absolutely nothing. This is it's implementation in the .Net source:
/// <devdoc>
/// <para>
/// Flushes data from the stream. This is meaningless for us, so it does nothing.
/// </para>
/// </devdoc>
public override void Flush() {
}
I'm using Flowcode technology to program a micro controller 16F877A.
from flowcode i'm sending 3 bytes UDP packets to a server listening on port 23456.
the problem is that the server never receives those packets. i used wireshark for tracing and it was able to detect the 3 bytes and its content.
below is my server code using c#
const int port_number=23456;
TcpListener server=new TcpListener( IPAddress.Any ,port_number);
Socket soc;
NetworkStream s;
bool exit=false;
Thread mythread;
thread code is here
void method()
{
try
{
server.Start();
soc = server.AcceptSocket();
s = new NetworkStream(soc);
StreamReader sr = new StreamReader(s);
textBox1.Text += sr.ReadLine();
if(soc.Connected==true && exit==false)
method();
}
catch(Exception es)
{
Console.WriteLine("{0}",es.Message);
}
}
do you think i need to change anything to be able to read those 3 bytes and process them.
i really appreciate your help.
You are using a TcpListening, but you are sending UDP packets? Try the UDPClient class: http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.aspx
Edit
To elaborate a little bit. A TCP Client will never receive UDP packets, since TCP and UDP are two separate protocols at the socket level. The socket will see you are listening for a TCP connection, it will receive the UDP datagram, see no listeners, and throw it away.
Apparently ICMP isn't the only way to create a Traceroute. This and this answer indicates it's possible to send a UDP packet (or any other) with a low TTL and wait for the ICMP message.
How would I go about implementing this in C#? System.IO.Sockets? The TCP objects? Anyone know of an easy/best way?
Update 1:
The following code seems to correctly throw an exception when the TTL is hit. How do I extract information from the returned UDP Packet?
How do I know that the UDP packet I'm receiving is intended for me (and not some other application on my host?)
public void PingUDPAsync(IPAddress _destination, short ttl)
{
// This constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient(21000);
udpClient.Ttl = ttl;
// udpClient.DontFragment = true;
try
{
udpClient.Connect(_destination, 21000);
// Sends a message to the host to which you have connected.
Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");
udpClient.Send(sendBytes, sendBytes.Length);
//IPEndPoint object will allow us to read datagrams sent from any source.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
// Blocks until a message returns on this socket from a remote host.
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
// Uses the IPEndPoint object to determine which of these two hosts responded.
Console.WriteLine("This is the message you received " +
returnData.ToString());
Console.WriteLine("This message was sent from " +
RemoteIpEndPoint.Address.ToString() +
" on their port number " +
RemoteIpEndPoint.Port.ToString());
udpClient.Close();
}
catch (SocketException socketException)
{
Console.WriteLine(socketException.ToString());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Yes, System.Net.Sockets should provide you all the primitive objects you would need to send/receive UDP/TCP packets. Plenty of documentation and samples online, the two articles you included in your question are very interesting and a good starting point :)
https://learningnetwork.cisco.com/thread/87497
You can check out the answer here that goes into detail on Cisco's UPD traceroute implementation. It is rather comprehensive and can easily adapted to target a specific UDP port. You do not get a UDP packet back from the target. Rather, you get an ICMP reply to indicate the traffic was not received. The UDP packet that you originate has a random response port number included and your host tracks what ports are used by what applications. When the ICMP response is sent back, it is sent to the host IP and the response port included in the UDP header. Your host will then see the port and know it is bound to your application. It then delivers the packet to your application.
I read 2 C# chat source code & I see a problem:
One source uses Socket class:
private void StartToListen(object sender , DoWorkEventArgs e)
{
this.listenerSocket = new Socket(AddressFamily.InterNetwork , SocketType.Stream , ProtocolType.Tcp);
this.listenerSocket.Bind(new IPEndPoint(this.serverIP , this.serverPort));
this.listenerSocket.Listen(200);
while ( true )
this.CreateNewClientManager(this.listenerSocket.Accept());
}
And other one uses TcpListener class:
server = new TcpListener(portNumber);
logger.Info("Server starts");
while (true)
{
server.Start();
if (server.Pending())
{
TcpClient connection = server.AcceptTcpClient();
logger.Info("Connection made");
BackForth BF = new BackForth(connection);
}
}
Please help me to choose the one. I should use Socket class or TcpListener class. Socket connection is TCP or UDP? Thanks.
UDP is connectionless, but can have a fake connection enforced at both ends on the socket objects. TCP is a stream protocol (what you send will be received in chunks on the other end), and additionally creates endpoint sockets for each accepted socket connection (the main listening socket is left untouched, although you'd probably need to call listen() again). UDP uses datagrams, chunks of data which are received whole on the other side (unless the size is bigger than the MTU, but that's a different story).
It looks to me like these two pieces of code are both using TCP, and so as the underlying protocol is the same, they should be completely compatible with each other. It looks as if you should use the second bit of code since it's higher level, but only the server can really use this, the client needs a different bit of code since it doesn't listen, it connects... If you can find the 'connecting' code at the same level of abstraction, use that.
In c# I am using the UdpClient.Receive function:
public void StartUdpListener(Object state)
{
try
{
udpServer = new UdpClient(new IPEndPoint(IPAddress.Broadcast, 1234));
}
catch (SocketException ex)
{
MessageBox.Show(ex.ErrorCode.ToString());
}
IPEndPoint remoteEndPoint = null;
receivedNotification=udpServer.Receive(ref remoteEndPoint);
...
However I am getting a socket exception saying that the address is not available with error code 10049
What do I do to negate this exception?
Here's the jist of some code I am currently using in a production app that works (we've got a bit extra in there to handle the case where the client are server apps are running on a standalone installation). It's job is to receive udp notifications that messages are ready for processing. As mentioned by Adam Alexander your only problem is that you need to use IPAddress.Any, instead of IPAddress.Broadcast. You would only use IPAddress.Broadcast when you wanted to Send a broadcast UDP packet.
Set up the udp client
this.broadcastAddress = new IPEndPoint(IPAddress.Any, 1234);
this.udpClient = new UdpClient();
this.udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.udpClient.ExclusiveAddressUse = false; // only if you want to send/receive on same machine.
And to trigger the start of an async receive using a callback.
this.udpClient.Client.Bind(this.broadcastAddress);
this.udpClient.BeginReceive(new AsyncCallback(this.ReceiveCallback), null);
Hopefully this helps, you should be able to adapt it to working synchronously without too much issue. Very similar to what you are doing. If you're still getting the error after this then something else must be using the port that you are trying to listen on.
So, to clarify.
IPAddress.Any = Used to receive. I want to listen for a packet arriving on any IP Address.
IPAddress.Broadcast = Used to send. I want to send a packet to anyone who is listening.
for your purposes I believe you will want to use IPAddress.Any instead of IPAddress.Broadcast. Hope this helps!
That error means the protocol cant bind to the selected IP/port combination.
I havent used UDP broadcast in ages, but I do recall you need to use different IP ranges.
There's nothing wrong with the way you have configured your UdpClient. Have you tried a different port number? Perhaps 1234 is already in use on your system by a different app.