Downloading a file using multiple connections and multihoming - c#

I am a student in my fourth year in university. My graduation project is a download manager which i intend to code with C#.
when checked the MSDN documentation the project looked easy. But the problem is that my teacher wants me to incorporate multihoming to the project. He want the download manager to:
split the file the user wants to download to multiple segments.
for each segment the DM should create a connection and request that segment from the server.
after all segments finish downloading the DM should combine the segments into one file.
If multihoming exists each connection should go(or route) thru different ISP (as when multihoming is used, the computer is connected to more than one ISP thru more than one network adapter) as this process should accelerate the download of the file.
I can accomplish the first three steps but I couldn't find a solution to the fourth step so can anyone pleas help me or guide me thru the right way.
I am not an experienced networking and protocol programer I have only choose C# because it simplify the process of sending and requesting files.

I believe that your answer lies with the ServicePoint.BindIPEndPointDelegate property, which you can set within your HttpWebRequest instance. Quoting MSDN:
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.
Basically, BindIPEndPointDelegate lets you select the local endpoint to use for your connection. You can retrieve the list of all local IP addresses using Dns.GetHostAddresses(Dns.GetHostName()), and then pick one at random within the delegate. You do, however, need to be careful to match the address family: If the remote endpoint is IPv6, you need to select a local IPv6 address.
I’m including some sample code below.
Uri uri = new Uri("http://google.com");
Random random = new Random();
IPAddress[] localAddresses = Dns.GetHostAddresses(Dns.GetHostName());
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.ServicePoint.BindIPEndPointDelegate =
(servicePoint, remoteEndPoint, retryCount) =>
{
var allowedLocalAddresses =
localAddresses.Where(localAddress =>
localAddress.AddressFamily == remoteEndPoint.AddressFamily).ToArray();
IPAddress selectedLocalAddress =
allowedLocalAddresses[random.Next(allowedLocalAddresses.Length)];
return new IPEndPoint(selectedLocalAddress, 0);
};
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
References:
How to change originating IP in HttpWebRequest
Choosing which IP the HTTP request is using when having multiple IPs (.NET)
Edit: I am not suggesting that you should actually pick local addresses at random for your project; the above code was just the simplest demonstration I could think of. If you’re establishing a number of concurrent connections and want to maximize load-balancing across all available adapters, then you should cycle through your local addresses; this would ensure that all adapters are handling an approximately equal number of connections each.

Related

DNS resolution fails on android

There is restriction on UDP response size for DNS protocol. It can only contain ~500bytes. When data exceeds the limit all the DNS servers sets flag "truncated" in response but some (google 8.8.8.8 for example) does not put any IPs in response others just put trimmed list. Utilities like nslookup and dig tries to ask DNS server by TCP to get full response but android does not. Instead it fails. The example of code that fails is bellow.
var host = "prdimg.affili.net";
var addressList = Dns.GetHostEntry(host).AddressList;
The Modernhttpclient uses gets IPs the same way so I cannot get files from prdimg.affili.net. To fix it I've implemented the temporary solution. I use GooglePublicDnsClient to resolve DNS and then change hostname to resolved ip with UriBuilder.
var builder = new UriBuilder(originalUrl);
builder.Host = ip;
But the solution has two disadvantages
it does not work for https because of certificate check
it does not work if server uses Vhosts
Can anyone propose a better solution?

Get external IP address of a website

I have seen many methods for easily retrieving the internal IP address of a machine or website. However, I can't seem to find a good way to retrieve the external IP address.
To clarify, if I provide a URL like bitbucket.org, I want to get the external IP address of bitbucket. Is there a web service out there that can easily do this?
EDIT: Suppose, for this case, that I am on the same network as bitbucket.org.
I am filling a database with information about all the websites our company manages. We want to keep track of the info and note periodic changes, with specific data. This program will be deployed on one of the local servers on the same network as the servers that the websites are running from. I believe the only good way of retrieving the external IP address for each site is to use an external web service.
You can use System.Net.Dns.GetHostEntry() to get IP address by the host name.
You could query an external public DNS server, e.g. Google's one at 8.8.8.8. From the command line
nslookup bitbucket.org 8.8.8.8
or in Linux dig bitbucket.org #8.8.8.8. There's a few C# libraries out there that will let you query a specific DNS server e.g. DnsNet built on top of this CodeProject article (found searching - I haven't tried it to recommend it). This does rely on Google continuing the service, though, but that seems safe.
You can use the ping utility. In windows, open up a command window by hitting the windows key + r and type
ping bitbucket.org
I think you can just use Dns.GetHostAddresses to get the IP Address. From the MSDN Documentation:
The GetHostAddresses method queries a DNS server for the IP addresses associated with a host name.
UPDATE:
If you are looking for a web service, try looking at whoisxmpapi.com. As you can see from this sample, they do provide the name server IP Address in their XML output. You can then use something like this to get the IP address directly from the name server!
If you are trying to get your "wan" ip instead of your local IP you could try something like this.
You could also add code like this inside a webservice and add it to the PC bitbucket is on (if it is really on your network and you can have access to install webservices).
Public Shared ReadOnly Property IpAddress() As String
Get
If String.IsNullOrWhiteSpace(_ipAddress) Then
Try
Dim webClient As New WebClient
Dim result As String = webClient.DownloadString("http://checkip.dyndns.org")
Dim fields = result.Split(" ")
_ipAddress = fields.Last
_ipAddress = _ipAddress.Replace("</body></html>", "")
Catch ex As Exception
_ipAddress = "errorFindingIp"
End Try
End If
Return _ipAddress
End Get
End Property

ASP.NET Request.ServerVariables yields local IP address not remote IP

Got an asp.net web page in c#. One thing we would like to do is track hits to the site including their IP address. I implemented some code (thanks to SO) but the logged IP address always seem to be local, ie: 192.168.x.x. I have tried it from a variety of devices, even my phone and Version MiFi just to make sure its not something weird with the ISP but the log always list the same 2-3 different internal ip addresses (seems to change a little as the day goes on).
Here is my function that gets the IP (again thanks to postings here on SO):
protected IPAddress GetIp(HttpRequest request)
{
string ipString;
if (string.IsNullOrEmpty(request.ServerVariables["HTTP_X_FORWARDED_FOR"]))
ipString = request.ServerVariables["REMOTE_ADDR"];
else
ipString = request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
IPAddress result;
if (!IPAddress.TryParse(ipString, out result))
result = IPAddress.None;
return result;
}
public void logHit()
{
IPAddress ip = GetIp(Request);
string sIP = ip.ToString();
}
I tried this as well which yields the same result:
HttpContext.Current.Request.UserHostAddress;
When I do a call on the client side using something like the service on appspot, it works just fine:
<script type="application/javascript">
function getip(json) {
//txtIP is a input box on the form
document.getElementById("txtIP").value = json.ip;
}
</script>
<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"></script>
I suppose I could do a round-about way by hitting that appspot link and parse it out but that seems like a whole lot of trouble for something that should be simple.
Could it be the IIS on the server? Some kind of redirect going on? The ip addresses logged are NOT the servers. The problem is I dont have direct access to it so I have to talk to the guys that admin it and would like to give them some direction before they just start changing things.
Thanks
Ernie
If the HTTP_X_FORWARDED_FOR header is truly supported, then I think this would not be either forward or reverse proxy server causing this, but more likely Dynamic Network Address Translation or Dynamic Port Address Translation, which is happening below the application layer on the TCP/IP stack and thus would not affect an HTTP request header.
There are many ways to configure NAT, most of which would not cause these symptoms, but it is certainly possible to configure NAT in a way that would present this problem. Dynamic NAT or Dynamic PAT would be two such examples, and I would suggest this is what you ask your network administrators.
For more on Dynamic NAT/PAT, with good examples, you could review: http://www.cisco.com/en/US/docs/security/asa/asa82/configuration/guide/nat_dynamic.html
In a typical NAT scenario, the request packets reach the NAT device (firewall or router) as:
FROM - 5.5.5.5 (public address of the client)
TO - 6.6.6.6 (the public address of the server)
The "typical" NAT configuration would rewrite only the destination, as follows:
FROM - 5.5.5.5
TO - 192.168.6.6 (the private address of the server)
In this typical case, the server would still see REMOTE_ADDR as 5.5.5.5, as that is the source address on the incoming request. Then, the packets would be returned to 5.5.5.5, and the response would return to the client successfully.
Now, in the case of dynamic PAT, for example, the request would reach the NAT device as follows:
FROM - 5.5.5.5
TO - 6.6.6.6
Then, the NAT device would rewrite both source and destination packets, maintaining this "dynamic" mapping for only the lifetime of the request:
FROM - 192.168.1.1:12345 (the dynamic PAT address)
TO - 192.168.6.6 (the private address of the server)
Now, when the server sees this request, it appears to be from private address 192.168.1.1. In fact, with a strict PAT all requests will appear to be from this address. In your case, there are 2 or 3 of these addresses, probably because you may have enough traffic that you risk running out of ports if you use only a single dynamic PAT address.
So, your REMOTE_ADDR is 192.168.1.1, because that is actually the source address on the request packets. There is no HTTP_X_FORWARDED_FOR, because the Dynamic PAT is occurring at a lower TCP/IP layer (address and not application).
Finally, the response is sent back to 192.168.1.1:12345, which routs to the NAT device, which for the duration of the request/response (see the Cisco documentation above) maps it back to 5.5.5.5, and then drops the "dynamic" mapping.
Everything worked perfectly, the client gets the response back, except that you have no idea of the actual client address from the viewpoint of the server. And if it is dynamic NAT in play, I don't see how you could get this information from the server.
Fortunately, you did exactly the right thing to get the information in javascript on the client, so this likely solves your problem as well as it could be solved.
It depends on your network structure. Simply a firewall or load balancer can change the variables which you are checking.
if you are using a load balancer check this:
How to get visitor IP on load balancing machine using asp.net
if your sever is behind a firewall check this:
Find if request was forwarded from firewall to IIS

How to mimic an IP Address - Device Simulator Required

I'm new here...been digging around for some help but figured I would join and ask for some guidance.
I'm looking to create an app that can create multiple "fake" devices. They need an IP Address and I'm guessing able to respond to ping. Being able to respond to WMI would also be nice. Kinda like a simulator. I'd like to create up to 50,000 devices but even starting with 1 would help.
What is needed for such an app? TCP Client/Listener? I've never done something like this before so please be gentle :)
You may install Virtual Network Adapter's (driver is included with Windows OS), but i have never used this. Driver for Virtual Network Adapter is here: %WINDIR%\Inf\Netloop.inf
You may use Command line tool called DevCon to add devices by script, like this:
devcon -r install %WINDIR% \Inf\Netloop.inf *MSLOOP
Installation unfortunatelly takes few seconds (on my Core Duo 2.0 laptop).
If you need to configure a lot of network cards you may use command line netsh.
Examples:
netsh in ip set address "Local Area Connection" static 10.0.0.1 255.0.0.0 10.0.0.1 1
netsh in ip add address "Local Area Connection" 10.0.0.2 255.0.0.0
netsh in ip set address "Local Area Connection 2" 10.0.0.3 255.0.0.0
netsh in ip set address "Local Area Connection 3" 10.0.0.4 255.0.0.0
netsh in ip set dns "Local Area Connection" static 10.0.0.250
netsh in ip set wins "Local Area Connection" static 10.0.0.250
You may dump/export current network configuration to a file (to see how current config looks):
netsh interface dump > file.txt
More netsh examples
Edit: removed informations not useful in this case.
If I'm understanding you correctly, unfortunately this will not be easy as you need to virtualize network adapters to do the job you want. an IP address is bound to a nic (physical or logical), not something that can be specified in higher layer code. VMWare Workstation does include a plugin for Visual studio, so perhaps you can use it to generate many virtual nics and assign them ip's programatically, but otherwise you need to write virtual network card drivers (probably in a non-.net language) to do it, if you don't use an existing virtualization tech. you can stack many IP addresses on a nic, but the computer communicating with it will know they are all the same network entity. if thats fine with you, then just add all the IPs you want to the card you have.
on to the second part of your query, since you want the IPs to be able to recieve and send data, their addresses will have to be routable, so you can't just pick any old IP address. if you are fine being behind a NAT wall, you could use 10.x.y.z to address them, but on the outside of the nat they would all appear to be using the same public IP to the outside world. in order to expose 50k publicly routable IP addresses, you would first have to register and buy them.
lastly you can't use TCPClient to do Echo/Ping, since they use the ICMP protocol, but instead use the System.Net and System.Net.NetworkInformation namespace. Here is some VB code to send a ping just to give you the flavor of it:
Imports System
Imports System.Net
Imports System.Net.NetworkInformation
Public Class Pinger
<System.Diagnostics.DebuggerNonUserCode()> _
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeComponent()
End Sub
Public Shared Function CanHostBePinged(ByVal IPAddr_DNS_OR_Host_Name As String) As Boolean
Dim p As New Ping
Dim po As New PingOptions
po.Ttl = 256
po.DontFragment = False
Dim stringOut As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDE"
Dim streamOut As Byte() = System.Text.Encoding.ASCII.GetBytes(stringOut)
Try
Dim reply As PingReply = p.Send(IPAddr_DNS_OR_Host_Name, 30, streamOut)
If reply.Status = IPStatus.Success Then
Return True
Else
Return False
End If
Catch ex As Exception
Return False
End Try
End Function
End Class
I know this thread is very old, but I am posting my idea for anyone who might visit this question.
The previous answers already made clear that it is very difficult to achieve what the OP is trying to achieve. But I think if anybody needs such functionality for testing purposes there is a very easy way to achieve it.
We can create a simple web app in Node or .NET or whatever environment is comfortable. The web app's UI will allow us to do the following operations.
Create a device with IP
Mark an IP as Online or Offline.
If IP is online it is pingable, else not.
At the same time, the web app also exposes an API that when supplied with an IP says to us whether the IP is pingable or not. This way we mock the ping operation to an IP. Let's name this web app as PingMock.
Now in the original app, we can create a TestPingService which instead of pinging, sends an HTTP request to PingMock. This way we will be able to test our business logic without having access to actual IPs.
For testing business logic the final output of the PingService matters and not from where the output comes. This is how unit testing is conducted.
The PingMock web app is just an example. We can mock the Ping operation in whichever way we like.

How can i get IP Address of my 3G modem?

My GPRS modem has got a sim card. it can connect Web. Web service give it a ip number. i need it. like that: http://www.your-ip-address.com/
How can i do that C#?
You can use the static method WebClient.DownloadString(url) to read your external IP address from any web service providing such data:
string ip = System.Net.WebClient.DownloadString("http://whatismyip.org/");
If you are going to use this in a production environment, better make sure that the URL you are pointing to, is guaranteed to stay around for the entire lifespan of your application. The best way is probably to host the web service yourself.
Also, you should add some error checking around this code, as it will fail if the internet connection or the web service is unavailable.
You can get a list of your IP addresses via DNS using the following code:
var name = Dns.GetHostName();
var entry = Dns.GetHostEntry(name);
foreach (var address in entry.AddressList) {
Console.WriteLine(address);
}
If you want the IP address as a property of the hardware, you can use the System.Management.ManagementClass with the name Win32_NetworkAdapterConfiguration. See http://msdn.microsoft.com/en-us/library/system.management.managementclass.aspx for details.
You can create a WebRequest to http://whatismyip.com/automation/n09230945.asp which houses only your IP address
Start here

Categories

Resources