UDP broadcast send from PHP and receive in C# - c#

I'm trying to send a broadcast UDP message to a C# application. I have tried the following code to send the message. Which I found on the php.net website as a comment to the socket_sendto manual page.
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1);
socket_sendto($sock, $broadcast_string, strlen($broadcast_string), 0, '255.255.255.255', $port);
?>
This doesn't work for me, maybe it's my network.
But it does work if I replace the broadcast IP '255.255.255.255' to my specific IP e.g. '192.168.1.128'. I can see this message coming in with Wireshark, while I can't see this using the above code. This leads me to believe there is something wrong with the PHP side of the code. I really want to use broadcasting or some kind of multicasting for my program, so I'm a bit stuck at the moment ;)
I use the following on the (C#) receiving end (for testing):
UdpClient subscriber = new UdpClient(15000);
IPEndPoint ep = new IPEndPoint(IPAddress.Any, 15000); ;
byte[] pdata = subscriber.Receive(ref ep);
string data = Encoding.ASCII.GetString(pdata);
MessageBox.Show(data);
subscriber.Close();
Any idea what could be the cause of this?

Try specifying the MSG_DONTROUTE flag in your script. Taking inspiration from this CodeGuru post, if this isn't specified the routers make the decision on whether or not to broadcast your message.
socket_sendto($sock, $broadcast_string, strlen($broadcast_string), MSG_DONTROUTE, '255.255.255.255', $port);

255.255.255.255 is a "limited" broadcast whereas your 192.168.1.255 is a "directed" broadcast.
Limited in simple terms means that it is only send within the LAN. LAN as defined by directly connected hosts, i.e. with no router in between. Routers--with a few exceptions--do not pass a limited broadcast but a directed broadcast.
Now, with your initial problem and question, I can only guess that you are sending your broadcast across a router.

Related

Why does a packet sent using PCap.NET not fill out the TCP options?

I am trying to use PCap.NET to send a SYN packet to a destination. When using the WinSock API I can see the TCP Options in Wireshark.... But when I use PCap.NET to build and send the packet, the options are not included. Here is the TCP layer I use to build the packet :
TcpLayer tcpLayer = new TcpLayer
{
SourcePort = _sourcePort,
DestinationPort = _destinationPort,
SequenceNumber = _seqNumber,
ControlBits = TcpControlBits.Synchronize,
Window = _windowSize,
};
This is the a WireShark ScreenGrab for sending a SYN using WinSock, where the TCP options are visible.
And this is the Wireshark ScreenGrab sending a SYN using PCap.NET, where the TCP options are not visible.
I understand that when building a Pcap TCP layer you can set the options property to None.... I haven't done that, thinking that by leaving it as its default that the options would send the same way it does for WinSock. Can anybody provide any explanation or advice for this problem. Thanks in advance for the help!
If you create a new TcpLayer, you need to set the Options property in order to have options in the TCP layer.
If you don't set the Options property, it will, by default, set to None.

How to send packet message for specific NIC in c#

I'm a beginner with Socket programming in c# and I wonder how to send packet data for specific NIC.
I knew there was a way to set specific network device using setsockopt in python3 like that
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, 25, str(str(netinterface) + '\0').encode('UTF-8')) // netinterface => 'eth1'
except OSError :
print("Failed set eth1")
there were eth0 and eth1 and I did send packet successfully to eth1.
I found a way set option to socket like this, but I dont know how to resolve NIC using this APIs.
UdpClient udpclient = new UdpClient(new IPEndPoint(IPAddress.IPv6Any, 15118));
IPAddress multicateAddress = IPAddress.Parse("FF02::1");
udpclient.JoinMulticastGroup(multicateAddress);
Socket uSocket = udpclient.Client;
uSocket.SetSocketOption() // <- How... to?
If there is tutorials or any documents, it will help me.
Please comment thx.
Whether bind your socket to a specific IP address of an interface on the NIC you're looking for or modify your OS routing table to send packets to a specific network through a specified interface.
UdpClient isn't just a socket, but anyway I don't see an issue in binding it to a specific IP. See the docs for details.

Unable to receive UDP packets

I'm attempting to send and receive UDP packets from the same machine using two separate programs but so far I've not been able to receive anything. I've attempted completely turning off my firewall and that still hasn't worked.
Sending program
var sender = new UdpClient(Dns.GetHostName(), 2055);
var data = new byte[] { 0, 1, 2, 3, 4, 5 };
sender.Send(data, data.Length);
Receiving program
var receiver = new UdpClient(2055);
var endPoint = new IPEndPoint(IPAddress.Any, 2055);
var data = receiver.Receive(ref endPoint);
System.Console.WriteLine("Data received");
I've even copy and pasted code from this tutorial http://www.codeproject.com/Articles/10649/An-Introduction-to-Socket-Programming-in-NET-using and still had no success.
The problem is in var sender = new UdpClient(Dns.GetHostName(), 2055);
You need to specify your local host IP which is 127.0.0.1 since you are on the same machine. This should work:
var sender = new UdpClient("127.0.0.1", 2055);
From About multicast IP addresses and ports (TechNet):
Multicast IP addresses are class-D addresses that fall within two ranges: 224.0.0.0 through 239.255.255.255 and FF00:0000:0000:0000:0000:0000:0000:0000 through FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. The addresses in the first range are Internet Protocol version 4 (IPv4) addresses. The addresses in the second range are Internet Protocol version 6 (IPv6) addresses.
For intranet use, it is recommended that you use IPv4 addresses in the range 239...*. Port numbers can range between 1 and 65535. The routers on the network over which you are transmitting your content must be multicast-enabled, meaning that they must be able to interpret class-D addresses or they will not be able to forward your multicast information to clients.
You have to use an IP address in this range because of network-level filtering. There's a table of commonly-used multicast addresses on Wikipedia.
Actually, the tutorial you're using notes this too:
UDP also supports multicasting i.e. sending a single datagram to multiple receivers. To do so, the sender sends a packet to an IP address in the range 224.0.0.1 – 239.255.255.255 (Class D address group).

Broadcasting UDP message from C# to Python

I'm trying to send a broadcast message from a C# app on one machine to a Python script on another. If I specify the Python machine's IP as my endpoint, I can send a message just fine. Here's how I'm sending my message:
const int PORT = 12345;
using (var sock = new UdpClient())
{
var endpoint = new IPEndPoint(IPAddress.Parse(remoteIP), PORT);
//var endpoint = new IPEndPoint(IPAddress.Broadcast, PORT);
byte[] bytes = Encoding.UTF8.GetBytes("hello, world!");
sock.Send(bytes, bytes.Length, endpoint);
}
On the Python side, I'm receiving as follows:
import socket
PORT = 12345
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', PORT))
#sock.bind(('<broadcast>', PORT))
while 1:
data,addr = sock.recvfrom(1024)
if not data: break
print(data)
I can send my message from one machine to another successfully. However, I have multiple machines to which I want my message to go (UDP broadcast), but when I use IPAddress.Broadcast as my endpoint, Python doesn't receive my message. I've also tried binding my Python socket to <broadcast>, but that doesn't help, and binding to my C# machine's IP gives me the error socket.gaierror: [Errno -3] Temporary failure in name resolution.
I don't know if this is an issue of C# not sending the broadcast or of Python not receiving it.
You can use a network analyzer such as Wireshark to verify the operation of your networking code. I suspect that if you do, you will find that no broadcast datagram is actually set.
Lacking a good, complete code example it's hard to say for sure what the reason would be. But the cause of this would most likely be because you have not set the Socket.EnableBroadcast property for your socket. It defaults to false and if not set to true, broadcast datagrams won't be sent even if you send to a broadcast address.

What does Socket.ReceiveMessageFrom()'s endpoint parameter?

I am writing a proxy application for iSCSI to do some diagnostic work (think Fiddler for iSCSI) - I'm trying to capture data one packet at a time, I don't want to read arbitrary sizes and end up getting all of one iSCSI packet and half of another - I really want to see the same kind of data as Wireshark would display for example. In doing this, I'm using Socket.ReceiveMessageFrom().
However, one of the parameters is called "endpoint", and I'm not quite sure what to do with it. Any clues? Here's my code, can you tell me if I'm completely off base:
Tuple<byte[], int> readOnePacket(TcpClient conn) {
var flags = SocketFlags.None;
EndPoint endpoint = null; /*** You can't set this to null!! ***/
byte[] buffer = new byte[10 * 0x100000];
int offset = 0;
int bytes_received;
do {
IPPacketInformation packet_information;
bytes_received = conn.Client.ReceiveMessageFrom(buffer, offset, BufferSize,
ref flags, ref endpoint, out packet_information);
if (flags == SocketFlags.Partial) {
// We only want to transfer full packets
offset = bytes_received;
continue;
}
} while (false);
return new Tuple<byte[], int>(buffer, bytes_received + offset );
}
It is not TcpClient.ReceiveMessageFrom(), but Socket.ReceiveMessageFrom()
If you take a look at the documentation, you will read the following:
An EndPoint, passed by reference, that
represents the remote server.
Edit:
Setting it to null is, indeed, a bad idea.
While not a direct answer to your question, I think this answer can still be useful (though lots of time passed since the question was asked).
Because I don't know if iSCSI works over TCP or over plain IP, I cannot offer a solution for your problem. But in general, TCP is a stream-oriented protocol, and doesn't have a notion of "message". On the other hand, IP is a datagram (i.e. message) oriented protocol, and it has notion of message. In your code, you're trying to read a "message" (IP construct) from TCP socket, and that will not work. Yes, TCP is based on IP, but IP datagrams are not visible on TCP level.
The problem you've mentioned (read full message, without reading into the next one) is applicable to TCP level only, because on IP you really can read one whole message. When you want the same thing on TCP level, you need to use a protocol with message support. Usually to achieve this you need to have you own protocol, based on TCP, with messages like this:
[msg header][msg body]
where [msg header] consists of something like:
[msg type][msg body length]
Msg type and msg body length have fixed length (say, 2 bytes for msg type and 4 bytes for body length), and msg body can have variable length, so you can read full header, then determine how long the body is, and based on that read full body.
Hope this helps.

Categories

Resources