I need to edit headers of UDP packet (and send it with edited headers), I think I must use raw sockets.
I tried something like this:
byte[] buffer = new byte[]{0x00,0x00};
string ip = "SomeIP"
Socket sk = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Raw);
sk.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
sk.SendTo(new byte[] { buffer }, new IPEndPoint(IPAddress.Parse(ip),2017));
But I still can't edit header :(
byte[] buffer = new byte[] { 0x00, 0x00 };
string ip = "SomeIP";
// Set Socket Type to 'Dgram' for connectionless and UDP since your working with UDP
Socket sk = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sk.SendTo(buffer, new IPEndPoint(IPAddress.Parse(ip), 2017));
Related
I know there are already many queries on this forum. I have searched and at the end I am stuck to this issue thats why I am asking it.
I have a number of devices which can communicate on UDP.
I want to query them for status update. This is my code.
List<IPAddress> iPAdd = new List<IPAddress>();
foreach (string s in ipaddress)
{
IPAddress ips = IPAddress.Parse(s);
iPAdd.Add(ips);
}
//The main socket on which the server listens to the clients
byte[] byteData = new byte[1024];
Byte[] dataToSend = new Byte[] { 0x8B, 0xB9, 0x00, 0x03, 0x05, 0x01, 0x09 };
try
{
serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
//Assign the any IP of the machine and listen on port number 1200
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Bind this address to the server
serverSocket.Bind(ipEndPoint);
foreach(IPAddress ip in iPAdd)
{
IPEndPoint ipe = new IPEndPoint(ip, 1024);
EndPoint e = (EndPoint)ipe;
eps.Add(e);
}
//Start sending data
foreach(EndPoint ep in eps)
{
serverSocket.BeginSendTo(dataToSend, 0, dataToSend.Length, SocketFlags.None, ep,
new AsyncCallback(OnSend), ep);
Thread.Sleep(50);
Receive(ep);
}
}
catch (Exception ex)
{
string mess = ex.Message;
}
receive method -
private void Receive(EndPoint ep)
{
Byte[] receiveBytes = new Byte[1024];
IPEndPoint localip = new IPEndPoint(IPAddress.Any, 1200);
UdpClient receivingUdpClient = new UdpClient(localip);
receivingUdpClient.Client.Receive(receiveBytes);
receivingUdpClient.Dispose();
}
Error I am receiving by receivingUdpClient is -
"A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied"
What Am I doing wrong.? If I am completely wrong then also.. Any suggestions and advice are welcome
I got the way to do what I wanted to do.
Here is the code and explaination of what I was trying to do. Hope it help others.
MY task - Needed to create udp connection between multiple devices of same kind that receive query on 1024 and replied on 1200.
At the end I realized its simple as it is for single client. Now I am thinking how silly of me getting confused by these many options available.
Here is the code -
public byte[] serverSocket(String IPadd)
{
Socket serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
Socket receiveClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
byte[] receivebytes = new byte[100] ;
try
{
byte[] dataToSend = new byte[] { 0x8B, 0xB9, 0x00, 0x03, 0x05, 0x01, 0x09 };
IPAddress iPAddress = IPAddress.Parse(IPadd);
int port = 1024;
IPEndPoint iPEnd = new IPEndPoint(iPAddress, port);
//Assign the any IP of the machine and listen on port number 1200
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1200);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
serverSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 2000);
serverSocket.Bind(ipEndPoint);
EndPoint ep = (EndPoint)iPEnd;
serverSocket.SendTo(dataToSend, ep);
Thread.Sleep(1000);
serverSocket.Receive(receivebytes);
}
catch(Exception ex)
{
}
finally
{
serverSocket.Dispose();
}
return receivebytes;
}
String IPadd is the string from the list of ipaddresses that I got from database. So here what I am doing is - I am calling udp Connection and disposing it after receiving data so that I can use the same socket object for other IP address.
See its as simple as that.
And last but not the least, the guys on this forum.. Thank you very much because your suggestions gave me a different look to think of.
For some reason I am having a hard time sending and receiving data from the same socket. Anyways here is my client code:
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); // endpoint where server is listening (testing localy)
client.Connect(ep);
// send data
client.Send(new byte[] { 1, 2, 3, 4, 5 }, 5);
// then receive data
var receivedData = client.Receive(ref ep); // Exception: An existing connection was forcibly closed by the remote host
Basically I want to create a protocol where I send a udp packet and then I expect a response. Just like the HTTP protocol for every request there is a response. This code works if the server is on a different computer. There might be the case where the server and client are on the same computer though.
Here is the server:
UdpClient udpServer = new UdpClient(UDP_LISTEN_PORT);
while (true)
{
var groupEP = new IPEndPoint(IPAddress.Any, 11000); // listen on any port
var data = udpServer.Receive(ref groupEP);
udpServer.Send(new byte[] { 1 }, 1); // if data is received reply letting the client know that we got his data
}
Edit
the reason why I cannot use tcp is because sometimes the client is behind a NAT (router) and it is simpler to do UDP hole punching than TCP.
Solution:
thanks to markmnl answer here is my code:
Server:
UdpClient udpServer = new UdpClient(11000);
while (true)
{
var remoteEP = new IPEndPoint(IPAddress.Any, 11000);
var data = udpServer.Receive(ref remoteEP); // listen on port 11000
Console.Write("receive data from " + remoteEP.ToString());
udpServer.Send(new byte[] { 1 }, 1, remoteEP); // reply back
}
Client code:
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000); // endpoint where server is listening
client.Connect(ep);
// send data
client.Send(new byte[] { 1, 2, 3, 4, 5 }, 5);
// then receive data
var receivedData = client.Receive(ref ep);
Console.Write("receive data from " + ep.ToString());
Console.Read();
(I presume you are aware that using UDP(User Datagram Protocol) does not guarantee delivery, checks for duplicates and congestion control and will just answer your question).
In your server this line:
var data = udpServer.Receive(ref groupEP);
re-assigns groupEP from what you had to a the address you receive something on.
This line:
udpServer.Send(new byte[] { 1 }, 1);
Will not work since you have not specified who to send the data to. (It works on your client because you called connect which means send will always be sent to the end point you connected to, of course we don't want that on the server as we could have many clients). I would:
UdpClient udpServer = new UdpClient(UDP_LISTEN_PORT);
while (true)
{
var remoteEP = new IPEndPoint(IPAddress.Any, 11000);
var data = udpServer.Receive(ref remoteEP);
udpServer.Send(new byte[] { 1 }, 1, remoteEP); // if data is received reply letting the client know that we got his data
}
Also if you have server and client on the same machine you should have them on different ports.
I'll try to keep this short, I've done this a few months ago for a game I was trying to build, it does a UDP "Client-Server" connection that acts like TCP, you can send (message) (message + object) using this. I've done some testing with it and it works just fine, feel free to modify it if needed.
here is my soln to define the remote and local port and then write out to a file the received data, put this all in a class of your choice with the correct imports
static UdpClient sendClient = new UdpClient();
static int localPort = 49999;
static int remotePort = 49000;
static IPEndPoint localEP = new IPEndPoint(IPAddress.Any, localPort);
static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), remotePort);
static string logPath = System.AppDomain.CurrentDomain.BaseDirectory + "/recvd.txt";
static System.IO.StreamWriter fw = new System.IO.StreamWriter(logPath, true);
private static void initStuff()
{
fw.AutoFlush = true;
sendClient.ExclusiveAddressUse = false;
sendClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sendClient.Client.Bind(localEP);
sendClient.BeginReceive(DataReceived, sendClient);
}
private static void DataReceived(IAsyncResult ar)
{
UdpClient c = (UdpClient)ar.AsyncState;
IPEndPoint receivedIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receivedBytes = c.EndReceive(ar, ref receivedIpEndPoint);
fw.WriteLine(DateTime.Now.ToString("HH:mm:ss.ff tt") + " (" + receivedBytes.Length + " bytes)");
c.BeginReceive(DataReceived, ar.AsyncState);
}
static void Main(string[] args)
{
initStuff();
byte[] emptyByte = {};
sendClient.Send(emptyByte, emptyByte.Length, remoteEP);
}
The following code sends a packet on port 15000:
int port = 15000;
UdpClient udp = new UdpClient();
//udp.EnableBroadcast = true; //This was suggested in a now deleted answer
IPEndPoint groupEP = new IPEndPoint(IPAddress.Broadcast, port);
string str4 = "I want to receive this!";
byte[] sendBytes4 = Encoding.ASCII.GetBytes(str4);
udp.Send(sendBytes4, sendBytes4.Length, groupEP);
udp.Close();
However, it's kind of useless if I can't then receive it on another computer. All I need is to send a command to another computer on the LAN, and for it to receive it and do something.
Without using a Pcap library, is there any way I can accomplish this? The computer my program is communicating with is Windows XP 32-bit, and the sending computer is Windows 7 64-bit, if it makes a difference. I've looked into various net send commands, but I can't figure them out.
I also have access to the computer (the XP one)'s local IP, by being able to physically type 'ipconfig' on it.
EDIT: Here's the Receive function I'm using, copied from somewhere:
public void ReceiveBroadcast(int port)
{
Debug.WriteLine("Trying to receive...");
UdpClient client = null;
try
{
client = new UdpClient(port);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
IPEndPoint server = new IPEndPoint(IPAddress.Broadcast, port);
byte[] packet = client.Receive(ref server);
Debug.WriteLine(Encoding.ASCII.GetString(packet));
}
I'm calling ReceiveBroadcast(15000) but there's no output at all.
Here is the simple version of Server and Client to send/receive UDP packets
Server
IPEndPoint ServerEndPoint= new IPEndPoint(IPAddress.Any,9050);
Socket WinSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
WinSocket.Bind(ServerEndPoint);
Console.Write("Waiting for client");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0)
EndPoint Remote = (EndPoint)(sender);
int recv = WinSocket.ReceiveFrom(data, ref Remote);
Console.WriteLine("Message received from {0}:", Remote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Client
IPEndPoint RemoteEndPoint= new IPEndPoint(
IPAddress.Parse("ServerHostName"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
Am trying to make a simple UDP application using C sharp,nothing sophisticated,connect,send some text,and receive it! but it keeps throwing this exception!
"An existing connection was forcibly closed by the remote host"!
The code :
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.SendTo(data, data.Length, SocketFlags.None, ipep);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)sender;
data = new byte[1024];
int recv = server.ReceiveFrom(data, ref tmpRemote);
Console.WriteLine("Message received from {0}:", tmpRemote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Console.WriteLine("Stopping client");
server.Close();
thanks =)
You should tell the system that you are listening for UDP packets on port 9050 before you call Receive.
Add server.Bind(ipep); after Socket server = new Socket(...);
Have you tried checking that the IP address is valid and the port is not being used for something else?
Windows:
Start > Run > "cmd" > "ipconfig".
Try turning off your firewall software.
If you do not know the IP of the answering server, you better do:
recv = server.Receive(data);
Here is my suggetion to your code. You can use a do-while loop using a condition (in my example it is an infinite loop):
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.ReceiveTimeout = 10000; //1second timeout
int rslt = server.SendTo(data, data.Length, SocketFlags.None, ipep);
data = new byte[1024];
int recv = 0;
do
{
try
{
Console.WriteLine("Start time: " + DateTime.Now.ToString());
recv = server.Receive(data); //the code will be stoped hier untill the time out is passed
}
catch { }
} while (true); //carefoul! infinite loop!
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
Console.WriteLine("Stopping client");
server.Close();
Here is my code
Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck.Bind(new IPEndPoint(IPAddress.Any, 0));
// Broadcast to find server
string msg = "Imlookingforaserver:" + udp_listen_port;
byte[] sendBytes4 = Encoding.ASCII.GetBytes(msg);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("255.255.255.255"), server_port);
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
sck.SendTo(sendBytes4, groupEP);
//Wait response from server
Socket sck2 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck2.Bind(new IPEndPoint(IPAddress.Any, udp_listen_port));
byte[] buffer = new byte[128];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udp_listen_port);
sck2.ReceiveFrom(buffer, ref remoteEndPoint); //<<< I never pass this line
I use above code to try find a server. First I broadcast a message and then I wait for a response from the server.
A test I made with the server written in C++ and running in Windows Vista, client written in C# and run on the same machine with server.
Problem is: The server can receive message which client broadcast, but client can not receive anything from server.
I try to write a client with C++ and it work like a charm, I think my problem is in C# client.
I would start listening on that port before you broadcast. You're using UDP which is connectionless so you could be missing your packet.
Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck.Bind(new IPEndPoint(IPAddress.Any, 0));
//Wait response from server
Socket sck2 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck2.Bind(new IPEndPoint(IPAddress.Any, udp_listen_port));
byte[] buffer = new byte[128];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udp_listen_port);
// Broadcast to find server
string msg = "Imlookingforaserver:" + udp_listen_port;
byte[] sendBytes4 = Encoding.ASCII.GetBytes(msg);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("255.255.255.255"), server_port);
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
sck.SendTo(sendBytes4, groupEP);
sck2.ReceiveFrom(buffer, ref remoteEndPoint);