UDP ping implementation in C# - c#

I'm trying to implement ping based on udp packets with C#. The idea is to send udp packets to wrong port and get back ICMP packets contating Port unreachable error. And the time elapsed between seding the udp packet and recieveing the icmp packet is a ping time. I do it like that:
// Start building the headers
//Console.WriteLine("Building the packet header...");
int messageSize = 64;
byte[] builtPacket, payLoad = new byte[messageSize];
UdpHeader udpPacket = new UdpHeader();
ArrayList headerList = new ArrayList();
Socket rawSocket = null;
SocketOptionLevel socketLevel;
// Initialize the payload
//Console.WriteLine("Initialize the payload...");
for (int i = 0; i < payLoad.Length; i++)
payLoad[i] = (byte)'0';
// Fill out the UDP header first
//Console.WriteLine("Filling out the UDP header...");
udpPacket.SourcePort = 33434;
udpPacket.DestinationPort = 33434;
udpPacket.Length = (ushort)(UdpHeader.UdpHeaderLength + messageSize);
udpPacket.Checksum = 0;
Ipv4Header ipv4Packet = new Ipv4Header();
// Build the IPv4 header
//Console.WriteLine("Building the IPv4 header...");
ipv4Packet.Version = 4;
ipv4Packet.Protocol = (byte)ProtocolType.Udp;
ipv4Packet.Ttl = 30;
ipv4Packet.Offset = 0;
ipv4Packet.Length = (byte)Ipv4Header.Ipv4HeaderLength;
ipv4Packet.TotalLength = (ushort)Convert.ToUInt16(Ipv4Header.Ipv4HeaderLength + UdpHeader.UdpHeaderLength + messageSize);
ipv4Packet.SourceAddress = sourceAddress;
ipv4Packet.DestinationAddress = destAddress;
// Set the IPv4 header in the UDP header since it is required to calculate the
// pseudo header checksum
//Console.WriteLine("Setting the IPv4 header for pseudo header checksum...");
udpPacket.ipv4PacketHeader = ipv4Packet;
// Add IPv4 header to list of headers -- headers should be added in th order
// they appear in the packet (i.e. IP first then UDP)
//Console.WriteLine("Adding the IPv4 header to the list of header, encapsulating packet...");
headerList.Add(ipv4Packet);
socketLevel = SocketOptionLevel.IP;
// Add the UDP header to list of headers after the IP header has been added
//Console.WriteLine("Adding the UDP header to the list of header, after IP header...");
headerList.Add(udpPacket);
// Convert the header classes into the binary on-the-wire representation
//Console.WriteLine("Converting the header classes into the binary...");
builtPacket = udpPacket.BuildPacket(headerList, payLoad);
// Create the raw socket for this packet
//Console.WriteLine("Creating the raw socket using Socket()...");
rawSocket = new Socket(sourceAddress.AddressFamily, SocketType.Raw, ProtocolType.Udp);
// Bind the socket to the interface specified
//Console.WriteLine("Binding the socket to the specified interface using Bind()...");
IPAddress bindAddress = IPAddress.Any;
rawSocket.Bind(new IPEndPoint(bindAddress, 0));
// Set the HeaderIncluded option since we include the IP header
//Console.WriteLine("Setting the HeaderIncluded option for IP header...");
rawSocket.SetSocketOption(socketLevel, SocketOptionName.HeaderIncluded, 1);
rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000);
Stopwatch timer = new Stopwatch();
try {
for (int i = 0; i < 5; i++) {
timer.Reset();
timer.Start();
int rc = rawSocket.SendTo(builtPacket, new IPEndPoint(destAddress, 0));
Console.WriteLine("Sent {0} bytes to {1}", rc, destAddress);
Socket icmpListener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
icmpListener.Bind(new IPEndPoint(sourceAddress, 0));
icmpListener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 });
icmpListener.Shutdown(SocketShutdown.Send);
byte[] buffer = new byte[4096];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
try {
int bytesRead = icmpListener.ReceiveFrom(buffer, ref remoteEndPoint);
timer.Stop();
Console.WriteLine("Recieved " + bytesRead + " bytes from " + destAddress + " in " + timer.ElapsedMilliseconds + "ms\n");
}
catch {
Console.WriteLine("Server is not responding!");
}
finally {
icmpListener.Close();
}
}
}
catch (SocketException err) {
Console.WriteLine("Socket error occurred: {0}", err.Message);
}
finally {
rawSocket.Close();
}
And it works from time to time. The thing is that some web-sites send me an icmp packet and some not. Actually at first they also were not sending then I used Windows ping to ping them and tracert to traceroute them. And changed port number and it worked. But not for all. I can ping only google.com and one more site but others don't send icmp packet back. The same situation with local network computers I tried to ping. I send udp packet and don't get icmp back.
I used wireshark to watch packets flying.
What am I doing wrong in here?

Related

UDP client not receiving data

I have a problem communicating with a UDP device
public IPEndPoint sendEndPoint;
public void senderUdpClient(byte message_Type, byte Command_Class, byte command_code,int argument1, int argument2)
{
string serverIP = "192.168.2.11";
int sendPort = 40960;
int receivePort = 40963;
// Calcul CheckSum
// We know the message plus the checksum has length 12
var packedMessage2 = new byte[12];
var packedMessage_hex = new byte[12];
// We use the new Span feature
var span = new Span<byte>(packedMessage2);
// We can directly set the single bytes
span[0] = message_Type;
span[1] = Command_Class;
span[2] = command_code;
// The pack is <, so little endian. Note the use of Slice: first the position (3 or 7), then the length of the data (4 for int)
BinaryPrimitives.WriteInt32LittleEndian(span.Slice(3, 4), argument1);
BinaryPrimitives.WriteInt32LittleEndian(span.Slice(7, 4), argument2);
// The checksum
// The sum is modulo 255, because it is a single byte.
// the unchecked is normally useless because it is standard in C#, but we write it to make it clear
var sum = unchecked((byte)packedMessage2.Take(11).Sum(x => x));
// We set the sum
span[11] = sum;
// Without checksum
Console.WriteLine(string.Concat(packedMessage2.Take(11).Select(x => $#"\x{x:x2}")));
// With checksum
Console.WriteLine(string.Concat(packedMessage2.Select(x => $#"\x{x:x2}")));
Console.WriteLine(string.Concat(packedMessage2.Take(1).Select(x => $#"\x{x:x2}")));
UdpClient senderClient = new UdpClient();
sendEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), sendPort);
try
{
senderClient.Connect(this.sendEndPoint);
senderClient.Send(packedMessage2, packedMessage2.Length);
//IPEndPoint object will allow us to read datagrams sent from any source.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), receivePort);
Thread.Sleep(5000);
// Blocks until a message returns on this socket from a remote host.
Byte[] receiveBytes = senderClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);
senderClient.Close();
MessageBox.Show("Message Sent");
}
catch (Exception err)
{
MessageBox.Show(err.ToString());
}
}
Form1
ObjHundler.senderUdpClient(1, 1, 0x24, 0 , 0);
there I build my message and I send it via port 40960
and I got a response via port 40963
Wireshark
On wireshark I send the message and the equipment sends a response but the code crashes in this line
Byte[] receiveBytes = senderClient.Receive(ref RemoteIpEndPoint);
Without filling in the table and without displaying any error message
Is there something missing from my code?
what could be the problem
Netstat -a cmd pour l'ip que j'utilise pour l'envoie 192.168.2.20
[CMD Netstat -a]
The solution =
you must create a UDPClient for reading.
It worked for me
public void senderUdpClient()
{
string serverIP = "192.168.2.11";
int sendPort = 40960;
int receivePort = 40963;
UdpClient senderClient = new UdpClient();
sendEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), sendPort);
try
{
senderClient.Connect(this.sendEndPoint);
senderClient.Send(packedMessage2, packedMessage2.Length);
//Creates a UdpClient for reading incoming data.
UdpClient receivingUdpClient = new UdpClient(receivePort);
//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);
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());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
//string returnData = Encoding.ASCII.GetString(receiveBytes);
senderClient.Close();
MessageBox.Show("Message Sent");
}
catch (Exception err)
{
MessageBox.Show(err.ToString());
}
}

Cannot connect to another computer over TCP

I am working on a project that transfers files over TCP. It is written in .NET 4.7. The program works while the client connects on the server that is on the same computer but when I send it to a friend and I try to connect it I get an error:
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
Currently the program only sends some information about the file that will be copied and is nothing is encrypted as I cannot send even these information.
Here's the code for the server (Invoke is used because it is run on a separate thread):
private void Server_Start()
{
try
{
// Set port on 13000
int port = 13000;
//Get the ip adress for the server
String localIp;
using (var client = new WebClient())
{
// Try connecting to Google public DNS and get the local endpoint as IP
// If failed to connect set IP as local IP
if (CheckForInternetConnection())
{
try
{
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect("8.8.8.8", 65530);
IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
localIp = endPoint.Address.ToString();
}
}
catch (Exception e)
{
localIp = "127.0.0.1";
}
}
else
{
localIp = "127.0.0.1";
}
}
IPAddress IP = IPAddress.Parse(localIp);
// Create listener and start listening
server = new TcpListener(IP, port);
server.Start();
// Buffer for data
Byte[] bytes = new byte[256];
String data = string.Empty;
this.Invoke((MethodInvoker)(() => Log.Items.Add("Server started on ip: " + IP.ToString())));
while (true)
{
// Accepting requests
TcpClient client = server.AcceptTcpClient();
// Get the stream object
NetworkStream stream = client.GetStream();
// Read length of file name
byte[] nameLength = new byte[4];
stream.Read(nameLength, 0, 4);
int nameSize = BitConverter.ToInt32(nameLength, 0);
// Read the name of file
byte[] name = new byte[nameSize];
stream.Read(name, 0, nameSize);
String fileName = Encoding.UTF8.GetString(name);
// Read size of file
byte[] fileSizeB = new byte[4];
stream.Read(fileSizeB, 0, 4);
int fileSize = BitConverter.ToInt32(fileSizeB, 0);
// Read start signal
byte[] startB = new byte[9+1];
stream.Read(startB, 0, 9);
String start = Encoding.UTF8.GetString(startB);
this.Invoke((MethodInvoker)(() => Log.Items.Add("Size of name: " + nameSize.ToString())));
this.Invoke((MethodInvoker)(() => Log.Items.Add("Name of file: " + fileName)));
this.Invoke((MethodInvoker)(() => Log.Items.Add("File size: " + fileSize.ToString())));
this.Invoke((MethodInvoker)(() => Log.Items.Add("Start signal: " + start)));
// Response to client
byte[] message = Encoding.UTF8.GetBytes("Testmessage");
stream.Write(message, 0, message.Length);
}
server.Stop();
Log.Items.Add("Server started on ip: " + IP.ToString());
}
catch (Exception e)
{
this.Invoke((MethodInvoker)(() => Log.Items.Add(e)));
}
}
And here is the code for the client:
private void button1_Click(object sender, EventArgs e)
{
IPAddress iP = IPAddress.Parse(ConnectIp.Text);
int port = 13000;
int buffersize = 1024;
TcpClient client = new TcpClient();
NetworkStream netStream;
// Try to connect to server
try
{
client.Connect(new IPEndPoint(iP, port));
}
catch(Exception ex)
{
this.Invoke((MethodInvoker)(() => Log.Items.Add(ex.Message)));
return;
}
netStream = client.GetStream();
String path = "D:\\testingEnv\\test1\\testing\\Matematika\\2017\\Školsko\\2017-SS-skolsko-B-1234-zad.pdf";
String Filename = Path.GetFileName(path);
// We wish to send some data in advance:
// File name, file size, number of packets, send start and send end
byte[] data = File.ReadAllBytes(path);
// First packet contains: name size, file name, file size and "sendStart" signal
byte[] nameSize = BitConverter.GetBytes(Encoding.UTF8.GetByteCount(Filename)); // Int
byte[] nameB = Encoding.UTF8.GetBytes(Filename);
byte[] fileSize = BitConverter.GetBytes(data.Length);
byte[] start = Encoding.UTF8.GetBytes("sendStart");
// Last packet constains: "sendEnd" signal to stop reading netStream
byte[] end = Encoding.UTF8.GetBytes("sendEnd");
// Creating the first package: nameSize, fileName, fileSize and start signal
byte[] FirstPackage = new byte[4 + nameB.Length + 4 + 9];
nameSize.CopyTo(FirstPackage, 0);
nameB.CopyTo(FirstPackage, 4);
fileSize.CopyTo(FirstPackage, 4 + nameB.Length);
start.CopyTo(FirstPackage, 4 + nameB.Length + 4);
// Send the first pckage
netStream.Write(FirstPackage, 0, FirstPackage.Length);
byte[] buffer = new byte[30];
// Read the response
netStream.Read(buffer, 0, 11);
netStream.Close();
client.Close();
}
A friend tried to port forward the port 13000 but it didn't work either. We even tried with the firewall being down but nothing. I searched on the internet but couldn't find any solutions to the problem.
One thing to note is that both functions are in the same application. I don't know if that is the cause of the problem.
Does anyone know how what is the problem here?
Thanks in advance
Have you tried to connect to your server with telnet ? "telnet localhost 13000" or from other computer with correct ip and address nbr ? Try that while debugging your server code. If telnet works, then client code has some problem..

C# Socket receive data and send and receive again

I have a lot of GPS devices. One of my device (as client) send this message every minutes on TCP "[3G*4700201934*0009*LK,0,1,61]"
and my server have to read the message from GPS device and reply to device, I mean my server must send this message "[3G*4700201934*0009*LK]" for getting GPS positions. If I can't send this message, GPS device doesn't send the positions of GPS.
My code:
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
//Sonsuz döngü sayesinde AgAkimini sürekli okuyoruz
while (true)
{
Socket client = listener.AcceptSocket();
Console.WriteLine("Connection accepted.");
var childSocketThread = new Thread(() =>
{
byte[] data = new byte[100];
int size = client.Receive(data);
string fromGPSMessage = string.Empty;
for (int i = 0; i < size; i++)
fromGPSMessage += Convert.ToChar(data[i]);
Console.WriteLine("Recieved data: " + fromGPSMessage);
//fromGPSMessage = [3G*4700201934*0009*LK,0,1,59]
string serverMessageToGPS = fromGPSMessage.Substring(0, fromGPSMessage.IndexOf(",")) + "]";
//serverMessageToGPS = [3G*4700201934*0009*LK]
Encoding ascii = Encoding.ASCII;
client.Send(ascii.GetBytes(serverMessageToGPS));
data = new byte[100];
size = client.Receive(data);
string newMessagefromGPSMessage = string.Empty;
for (int i = 0; i < size; i++)
newMessagefromGPSMessage += Convert.ToChar(data[i]);
Console.WriteLine("New Message Data: " + newMessagefromGPSMessage);
client.Close();
});
childSocketThread.Start();
}
sometimes there is no new message data:
I can send message to device but I don't know how to get second message from GPS device.
You should create TCP OnReceive event. So when new data comes, OnReceive event executed and you can parse data.
In your code, you have written client.Receive(data), so it will receive data single time. To receive all data, you have to implement OnReceive event or you can put client.Receive(data) method in loop with threading.
It sounds like you need to read up on TcpClient: MSDN documentation
The example on that page shows you how to send data, and also how to read data returned to you.

how can i send Full name in TCP service in 2nd time?

When i send data through TCP server to client first time full name retrieved when i again send the another name like book it retrieved as (ook) in C sharp
client side code
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
while (true)
{
IPEndPoint localEndPoint;
localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.2"), 1);
try
{
sck.Connect(localEndPoint);
}
catch
{
Console.Write("Unable to connect to remote end point!\r\n");
);
}
Console.Write("Enter Text: ");
string text = Console.ReadLine();
byte[] data = Encoding.ASCII.GetBytes(text);
sck.Send(data);
Console.Write("Data Sent!\r\n");
sck.Close();
Console.ReadLine();
Server Side Code
while (true)
{
Socket accepted = sck.Accept();
Buffer = new byte[accepted.SendBufferSize];
int bytesRead = accepted.Receive(Buffer);
byte[] formatted = new byte[bytesRead];
for (int i = 0; i < bytesRead; i++)
{
formatted[i] = Buffer[i];
//Console.WriteLine(Buffer[i] + "\r\n");
}
//string strData = Encoding.ASCII.GetString(Buffer);
string strData = Encoding.ASCII.GetString(formatted);
Console.Write(strData + "\r\n");
accepted.Close();
}
There is something which I don't understand, you use Buffer as a variable but that is a type in C#, I don't know where and how you declare it.
Anyway, I would do it like this:
while (true)
{
Socket accepted = sck.Accept();
byte[] buffer = new byte[1024];
int ret=0;
StringBuilder sb= new StringBuilder();
while ((ret=accepted.Receive(buffer)) > 0)
{
sb.Append(Encoding.ASCII.GetString(buffer, 0, ret));
}
Console.Write(sb.ToString() + "\r\n");
accepted.Close();
}
In order to keep a dialog between both sockets you need something called a protocol, which means you know when you have received the whole data then you reply to the sender. A protocol could be: send a packet which inform what you are going to send, length of the message mainly. Other way is to stop reading when something comes into the message, for example the string "#END#" the return character '\r', etc. If you only want to send one single message and received back a reply message one thing you can do, however, is to shutdown the client part, only the send part Socket.Shutdown(SocketShutdown.Send);, with that, the sender tells the receiver it has sent all data, the receiver receives that signal and then it can send a reply message to the sender.
The client:
sck.Send(data);
Console.Write("Data Sent!\r\n");
// tell the server we have done sending data.
sck.Shutdown(SocketShutdown.Send);
// Now receive from the server
byte[] buffer = new byte[1024];
int ret = 0;
StringBuilder sb = new StringBuilder();
while ((ret = sck.Receive(buffer)) > 0)
{
sb.Append(Encoding.ASCII.GetString(buffer, 0, ret));
}
Console.Write(sb.ToString() + "\r\n");
sck.Close();
The server
while (true)
{
Socket accepted = sck.Accept();
byte[] buffer = new byte[1024];
int ret=0;
StringBuilder sb= new StringBuilder();
while ((ret=accepted.Receive(buffer)) > 0)
{
sb.Append(Encoding.ASCII.GetString(buffer, 0, ret));
}
Console.Write(sb.ToString() + "\r\n");
byte[] reply = Encoding.ASCII.GetBytes("I've got it!");
accepted.Send(reply);
accepted.Close();
}

TCP IP Server with acknowledgement and receive data again

I have developed TCP/IP Server in C# listening on port and a GPS device is sending the data to server.
Initially, the device sends the IMEI number to server and server acknowledges with 01. After receiving the acknowledgement by device, a new packet of data is sent to server.
I am able to get IMEI number by TCP Server and after sending acknowledgement, i am not able to receive new packet data from client. I am including my code below also. Please let me know where i am wrong.
I have tested using hercules tcp server tool and next data packet is receiving successfully but from my application it is not working.
try
{
IPAddress ipAdress = IPAddress.Parse(ConfigurationManager.AppSettings["Server"].ToString());
// You can use local IP as far as you use the
//same in client
// Initializes the Listener
TcpListener myList = new TcpListener(ipAdress, int.Parse(ConfigurationManager.AppSettings["Port"].ToString()));
for (; ; )
{ // Run forever, accepting and servicing connections
//Start Listeneting at the specified port
myList.Start();
Console.WriteLine("Server running - Port: 8000");
Console.WriteLine("Local end point:" + myList.LocalEndpoint);
Console.WriteLine("Waiting for connections...");
Socket socket = myList.AcceptSocket();
// When accepted
Console.WriteLine("Connection accepted from " + socket.RemoteEndPoint);
byte[] b = new byte[1000];
int k = socket.Receive(b);
Console.WriteLine("echoed {0} bytes.", k);
Console.WriteLine("Reading IMEI....");
string hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, b.Length));
File.WriteAllText(#"C:\ClientFiles\testIMEI", hexStr);
ASCIIEncoding asen = new ASCIIEncoding();
string response = "01";
Console.WriteLine("Ackowledgement Data - " + response);
//
int sentBytes = socket.Send(asen.GetBytes(response));
Console.WriteLine("Acknowledgement data sent!\n");
int count = 0;
while (socket.Poll(-1, SelectMode.SelectRead))
{
b = new byte[1000];
k = socket.Receive(b);
if (k > 0)
{
count++;
Console.WriteLine("Reading Client Data - Count - " + count.ToString() + " and lenght " + k.ToString());
hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, b.Length));
File.WriteAllText(#"C:\ClientFiles\testData" + count.ToString(), hexStr);
}
}
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
myList.Stop();
}
catch (Exception ex)
{
File.WriteAllText(#"C:\ClientFiles\Error.txt", ex.Message + "****" + ex.InnerException);
}
I don't see any error in the program, except these comments:
// Don't use the b.Length in this command:
string hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, b.Length));
// use k instead, the numbers actually read, not the length of the buffer.
string hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, k));
while (socket.Poll(-1, SelectMode.SelectRead))
{
// b has been allocated, don't need this
// b = new byte[1000];
k = socket.Receive(b);
if (k > 0)
{
count++;
Console.WriteLine("Reading Client Data - Count - " + count.ToString() + " and lenght " + k.ToString();
// use k not Length
hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, k /*b.Length*/));
File.WriteAllText(#"C:\ClientFiles\testData" + count.ToString(), hexStr);
}
}
Do you know if the Poll command ever returns? May be it raises an error and you are missing that one. Check it out.

Categories

Resources