I am trying to make some UDP communication between 2 different address, so my sending code looks like:
var localEndpoint = new IPEndPoint(IpAddress.Parse("192.168.2.10"), 51111)
var remoteEndpoint = new IPEndPoint(IpAddress.Parse("192.168.1.10"), 51111)
var sender = new UdpClient (localEndpoint)
sender.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
sender.Send (request.RawRequest, request.RawRequest.Length, remoteEndpoint) |> ignore
sender.Close ()
As you see those are 2 different address, so I am binding interface address to my client and turning off routing. But when I try this I am getting unreachable network message, but when I try same address families well it works.
I also do broadcast to this destination (that is 192.168.1.2) where endpoint is:
new IPEndPoint(IpAddress.Parse("255.255.255.255"), 51111)
sender.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
And it works.
What am I doing wrong?
Related
I am working on a service discovery implementation in C#. In an attempt to get around some issues, I have implemented both broadcast and multicast, simplified to the snippets shown.
Client side broadcast:
var requestData = new byte[]{ /* Whatever */}
// Configure broadcast
var ipBroadcastEndPoint = new IPEndPoint(IPAddress.Broadcast, 12301);
var broadcastServerEp = new IPEndPoint(IPAddress.Any, 0);
var broadcastClient = new UdpClient {EnableBroadcast = true};
broadcastClient.Client.Bind(_broadcastServerEp);
// Send a request:
broadcastClient.Send(requestData, requestData.Length, ipBroadcastEndPoint);
// Listen for a reply:
var broadcastserverEp = new IPEndPoint(IPAddress.Any, 0);
var broadcastserverResponseData = broadcastClient.Receive(ref broadcastserverEp);
Client side multicast:
var requestData = new byte[]{ /* Whatever */}
// Configure multicast
var ipMulticastEndPoint = new IPEndPoint(IPAddress.Parse("239.255.255.253"), 12302);
var multicastServerEp = new IPEndPoint(IPAddress.Any, 0);
var multicastClient = new UdpClient(AddressFamily.InterNetwork);
multicastClient.JoinMulticastGroup(IPAddress.Parse("239.255.255.253"), 32);
multicastClient.Client.Bind(_multicastServerEp);
// Send a request:
multicastClient.Send(requestData, requestData.Length, ipMulticastEndPoint);
// Listen for a reply:
var multicastserverEp = new IPEndPoint(IPAddress.Any, 0);
var multicastserverResponseData = multicastClient.Receive(ref multicastserverEp);
Server side broadcast:
// Listen for broadcast
Task.Run(() =>
{
var broadcastServer = new UdpClient(12301);
while(/**/)
{
var broadcastclientEp = new IPEndPoint(IPAddress.Any, 0);
var broadcastclientRequestData = broadcastServer.Receive(ref broadcastclientEp);
// Reply to broadcast:
var responseData = new byte[]{ /* Whatever */}
broadcastServer.Send(responseData, responseData.Length, broadcastclientEp);
}
}
Server side multicast:
// Listen for multicast
Task.Run(() =>
{
var multicastServer = new UdpClient(12302);
multicastServer.JoinMulticastGroup(IPAddress.Parse("239.255.255.253"));
while(/**/)
{
var multicastclientEp = new IPEndPoint(IPAddress.Any, 0);
var multicastclientRequestData = multicastServer.Receive(ref multicastclientEp);
// Reply to multicast:
var responseData = new byte[]{ /* Whatever */}
multicastServer.Send(responseData, responseData.Length, multicastclientEp);
}
}
If both client and server components are running on the same computer, both broadcast and multicast work as expected.
If both client and server components are on different computers in the same subnet, broadcast works, multicast works in one direction only (two computers in a given WLAN topology, multicast works when one of them is in the server role, but not the other way around).
If both client and server components are on different subnets in the same corporate network, neither broadcast or multicast works.
I'd like to get this to work reliably across subnets. From what I've learned so far, I know broadcast won't work, but multicast should.
Is there some magic to the selection of multicast addresses and/or port numbers? In other words, are there specific addresses and ports I should or should not be using for it to work reliably regardless of network topology? Are there address/port combinations which are customarily filtered or customarily kept open? Are there any configuration options I have overlooked?
Allowing multicast traffic to pass between subnets is controlled entirely by the routers between those subnets.
The routers need to be configured to either with static multicast routes, or to accept IGMP messages from hosts to set up multicast groups as they are joined.
I have this code, but I don't know if I am well connected or joined to the multicast group. I can send and receive messages through the normal IP "ip". But I don't know if I should do anything more to receive messages through multicast. I have this code:
public void UDPConnect()
{
socket = new UdpClient(25504);
try
{
endPoint = new IPEndPoint(IPAddress.Parse(ip), 2600);
socket.JoinMulticastGroup(IPAddress.Parse(multicastIP));
socket.Connect(endPoint);
byte[] sendBytes = Encoding.ASCII.GetBytes("Hello, from the client");
socket.Send(sendBytes, sendBytes.Length);
ConnectToServer();
}
catch (Exception e)
{
print("Exception thrown " + e.Message);
}
}
public void ConnectToServer()
{
InitializeClientData();
isConnected = true;
StartCoroutine(ClientSend.VisualStartupCor());
socket.BeginReceive(ReceiveCallback, null);
}
public void ReceiveCallback(IAsyncResult _result)
{
try
{
byte[] _data = socket.EndReceive(_result, ref endPoint);
socket.BeginReceive(ReceiveCallback, null);
if (_data.Length < 4)
{
Instance.Disconnect();
return;
}
HandleData(_data);
}
catch
{
Disconnect();
}
}
And this is my server code, just too simple. I just wanna to test if I can send and receive for the Client. As you can see, I have put the multicast IP that I use (231.1.1.10) in the Send method. When I send a message from the client, this server answers by sending the same message to the client. My client, in Unity, detects this message. It means that the multicast connection is successful?
var udp = require('dgram');
// --------------------creating a udp server --------------------
// creating a udp server
var server = udp.createSocket('udp4');
// emits when any error occurs
server.on('error',function(error){
console.log('Error: ' + error);
server.close();
});
// emits on new datagram msg
server.on('message',function(msg,info){
console.log('Data received from client : ' + msg.toString());
console.log('Received %d bytes from %s:%d\n',msg.length, info.address, info.port);
//sending msg
server.send(msg,info.port,'231.1.1.10',function(error){
if(error){
client.close();
}else{
console.log('Data sent !!!');
}
});
});
//emits when socket is ready and listening for datagram msgs
server.on('listening',function(){
var address = server.address();
var port = address.port;
var family = address.family;
var ipaddr = '192.XXX.X.XX';
console.log('Server is listening at port' + port);
console.log('Server ip :' + ipaddr);
console.log('Server is IP4/IP6 : ' + family);
console.log(address);
});
//emits after the socket is closed using socket.close();
server.on('close',function(){
console.log('Socket is closed !');
});
server.bind(2600);
UDP doesn't have a connected status, when you call a JoinMulticastGroup the socket sends a IGMP (Internet Group Management Protocol) packet to the service requesting membership to the multicast group.
If the client is accepted to the group, you can start receiving data on the socket
socket.BeginReceive(ReceiveCallback, null);
Basically there is no way to know if the server is going to send you a message, the point of UDP is to not maintain a connection. You could create a method to ping (send a message) the server and force it to multicast, which sort of looks like what you are trying to do with the "Hello, from the client" message
For more info on multicast groups check out this link
I've made a programm, which sends HTTP-webrequests.
To secure these requests being sent, I want to have the ability to define an IP, over which the request should be sent.
So in case of the default exit not working the request should be sent via another exit.
I've tried doing that by using IPEndPoint and Sockets but somehow it's not working.
Here is my Code so far
public Response ExecuteRequest(RequestData requestData, NetworkAddress exit) {
Tracer.Info("Versuche Request über HTTP abzusetzen.");
if (!PrepareIpEndPoint(Address, exit)) {
return null;
}
Address = new Uri(PlaceholderReplacer.ReplacePlaceholders(Address.ToString(), requestData));
return RequestExecutor.ExecuteRequest(Address);
}
private bool PrepareIpEndPoint(Uri url, NetworkAddress exit) {
Tracer.Debug(string.Format("Setze den IP-Endpoint auf{0}", exit));
var ipEndPoint = new IPEndPoint(IPAddress.Parse(exit.Address), 0);
var tempSocket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tempSocket.Bind(ipEndPoint);
tempSocket.Connect(ipEndPoint);
return tempSocket.Connected;
}
the above code is throwing SocketExceptions.
Any ideas are greatly appreciated.
Thanks, Josh
Remove this line: (it's for opening up a port for accepting clients)
tempSocket.Bind(ipEndPoint);
You want to act as a client by connecting to the server with:
tempSocket.Connect(ipEndPoint);
Are you really sure that you want to connet to port zero, i'm pretty sure this is not a valid choice. (standard HTTP = 80, HTTPS = 443)
var ipEndPoint = new IPEndPoint(IPAddress.Parse(exit.Address), 80);
I'm now using a socket server in C# but I can only bind it to 127.0.0.1.
But it has to bind to my VPS IP. Even if I try to bind to my hamachi IP, it doesn't work.
I use:
ServerSocketSettings Settings = new ServerSocketSettings
{
MaxConnections = Config.ServerMaxConnections,
NumOfSaeaForRec = Config.ServerMaxConnections,
Backlog = 30,
MaxSimultaneousAcceptOps = 15,
BufferSize = 512,
Endpoint = new IPEndPoint(IPAddress.Parse("25.168.77.190"), Config.ServerPort)
};
this._serverSocket = new ServerSocket(Settings);
Then I do:
this.ListenSocket = new Socket(this.Settings.Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.ListenSocket.Bind(this.Settings.Endpoint);
this.ListenSocket.Listen(this.Settings.Backlog);
the this.Settings is the value of the code above.
When I run it, I get:
The requested address is not valid in its context
I'm wondering why it doesn't work.
You should bind the Listening Socket only to a specific Interface if you want to limit the availability of the service to this network segment.
If this is not needed you can just bind it to any ip address with
this.ListenSocket.Bind(new IPEndPoint(IPAddress.Any));
We have a load balanced (NLB) ASP.NET web app which sends email.
The servers are dual homed with an external facing and internal (behind firewall) facing IP. The Mail server is behind the firewall.
We have been seing a problem where the SMTPClient class throws an exception stating it is unable to connect to the SMTP server.
The networking guys are telling us they are seeing attempts to connect to the SMTP server from the external facing IP address (which the firewall is blocking)
From my (admittedly patchy) knowledge of network enabled applications I thought that the local IP binding would be decided based on the destination, i.e. if the routing tables say the IP address can be accessed through a particular NIC than that is the IP the outbound request is generated from. Am I wrong?
looking at SmtpClient.ServicePoint I'm beginning to think that we might be and that we can (should) force an explicit binding to a particular IP?
specifically I've been looking at
ServicePoint.BindIPEndPointDelegate Property
from that page...
Remarks :Some load balancing techniques
require a client to use a specific
local IP address and port number,
rather than IPAddress.Any (or
IPAddress.IPv6Any for Internet
Protocol Version 6) and an ephemeral
port. Your BindIPEndPointDelegate can
satisfy this requirement.
it just seems a little odd to me that I'd need to do that but perhaps thats common in this type of environment?
You need to do something like this...
public delegate IPEndPoint BindIPEndPoint(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount);
private IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount) {
if (retryCount < 3 && ddSendFrom.SelectedValue.Length > 0)
return new IPEndPoint(IPAddress.Parse("192.168.1.100"), 0); //bind to a specific ip address on your server
else
return new IPEndPoint(IPAddress.Any, 0);
}
protected void btnTestMail_Click(object sender, EventArgs e) {
MailMessage msg = new MailMessage();
msg.Body = "Email is working!";
msg.From = new MailAddress("me#me.com");
msg.IsBodyHtml = false;
msg.Subject = "Mail Test";
msg.To.Add(new MailAddress("you#you.com"));
SmtpClient client = new SmtpClient();
client.Host = "192.168.1.1";
client.Port = 25;
client.EnableSsl = false;
client.ServicePoint.BindIPEndPointDelegate = new System.Net.BindIPEndPoint(BindIPEndPointCallback);
client.Send(msg);
}