I'm running this application on a server that has assigned 5 IPs. I use HttpWebRequest to fetch some data from a website. But when I make the connection I have be able to specify which one of the 5 IPs to make the connection from. Does HttpWebRequest support this? If it doesn't can I inherit a class from it to change it's behavior? I need so ideas here.
My code right now is something like:
System.Net.WebRequest request = System.Net.WebRequest.Create(link);
((HttpWebRequest)request).Referer = "http://application.com";
using (System.Net.WebResponse response = request.GetResponse())
{
StreamReader sr = new StreamReader(response.GetResponseStream());
return sr.ReadToEnd();
}
According to this, no. You may have to drop down to using Sockets, where I know you can choose the local IP.
EDIT: actually, it seems that it may be possible. HttpWebRequest has a ServicePoint Property, which in turn has BindIPEndPointDelegate, which may be what you're looking for.
Give me a minute, I'm going to whip up an example...
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com");
req.ServicePoint.BindIPEndPointDelegate = delegate(
ServicePoint servicePoint,
IPEndPoint remoteEndPoint,
int retryCount) {
if (remoteEndPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) {
return new IPEndPoint(IPAddress.IPv6Any, 0);
} else {
return new IPEndPoint(IPAddress.Any, 0);
}
};
Console.WriteLine(req.GetResponse().ResponseUri);
Basically, the delegate has to return an IPEndPoint. You can pick whatever you want, but if it can't bind to it, it'll call the delegate again, up to int.MAX_VALUE times. That's why I included code to handle IPv6, since IPAddress.Any is IPv4.
If you don't care about IPv6, you can get rid of that. Also, I leave the actual choosing of the IPAddress as an exercise to the reader :)
Try this:
System.Net.WebRequest request = System.Net.WebRequest.Create(link);
request.ConnectionGroupName = "MyNameForThisGroup";
((HttpWebRequest)request).Referer = "http://application.com";
using (System.Net.WebResponse response = request.GetResponse())
{
StreamReader sr = new StreamReader(response.GetResponseStream());
return sr.ReadToEnd();
}
Then try setting the ConnectionGroupName to something distinct per source ip you wish to use.
edit: use this in conjunction with the IP binding delegate from the answer above.
Related
The application iterates through around 500 webrequests, at random the request returns a 500-error from the server. I belive their is either a problem with the amount of requests made or that at some point the information takes to long to read into the datatable that causes the connection to fail. But these are just guesses on my part. Is there a smarter way to iterate through all of the requests or to use another approach?
I have other iterations made in the same manner for other requests, none of them are as hefty as this one and they don't throw any errors from the server.
foreach (DataRow row in dt.Rows)
{
string url = row["href"].ToString();
HttpWebRequest productsDetails = (HttpWebRequest)WebRequest.Create(url);
productsDetails.Credentials = nc;
productsDetails.Method = "GET";
productsDetails.Timeout = 5000;
productsDetails.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
using (HttpWebResponse productsDetailsResponse = (HttpWebResponse)productsDetails.GetResponse())
{
var detailedRespons = productsDetailsResponse.GetResponseStream();
XDocument detailedResponsDoc = XDocument.Load(detailedRespons);
//foreach (XElement xe4 in detailedResponsDoc.Descendants("product_option_value"))
//{
// DataRow row4 = dt4.NewRow();
// row4["href"] = xe4.Attribute(xlink + "href").Value;
// dt4.Rows.Add(row4);
//}
string p1 = detailedResponsDoc.Root.Element("combination").Element("id").Value;
string p2 = detailedResponsDoc.Root.Element("combination").Element("reference").Value;
string p3 = detailedResponsDoc.Root.Element("combination").Element("price").Value;
string p4;
foreach (XElement xe2 in detailedResponsDoc.Descendants("product_option_value"))
{
p4 = (xe2.Value);
DataRow row5 = test.NewRow();
row5["id"] = p1;
row5["referemce"] = p2;
row5["price"] = p3;
row5["POV"] = p4;
test.Rows.Add(row5);
DataRow row4 = dt4.NewRow();
row4["href"] = xe2.Attribute(xlink + "href").Value;
dt4.Rows.Add(row4);
}
productsDetailsResponse.Close();
}
}
}
}
}
catch (WebException webex)
{
WebResponse errResp = webex.Response;
using (Stream respStream = errResp.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
string text = reader.ReadToEnd();
MessageBox.Show("yttre:" + text);
}
}
The error message is a a generic 500 exception from the server, referring me to contact the host. The host don't see anything and the little i have found in some kind of error log on the server don't contain any information.
Make sure the server is not blocking you, some servers have firewalls that block repetitive connections from a single IP address as they believe it will be an attack.
This is a normal and often cannot be disabled by hosts as it is a security feature.
Add a delay to the requests and see if the server responds correctly, if this works, then the server may be blocking you.
Try to make similar requests on a local server like XAMP, if the same errors occur this could be a code fault, like the information being passed to the server (Headers, Post, Get and etc).
Try reusing HttpWebRequest to avoid overhead if you repeatedly create an object, try using asynchronous methods.
There are many variables as to why there might be errors, but the chance of being server-related or HttpWebRequest is the most likely.
I have four application server for my application.Application is working on all server using load balancing.If one of my server goes down I have to check it manually using my system hosts file.To avoid this manual process I have created one program using C#.I write server IP address one by one in host file and remove previous one.
private void RunWithUAC()
{
List<string> lstIPAddress = new List<string>();
lstIPAddress.Add("1.1.1.1 example.com");
lstIPAddress.Add("1.1.1.1 example.com");
lstIPAddress.Add("1.1.1.1 example.com");
lstIPAddress.Add("1.1.1.1 example.com");
var systemPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
Console.WriteLine(systemPath);
var path = #"C:\Windows\System32\drivers\etc\hosts";
foreach (var item in lstIPAddress)
{
System.IO.File.WriteAllText(path, string.Empty);
try
{
File.WriteAllText(path, item);
WebRequest request = WebRequest.Create("https://example.com");
request.Timeout = 10000;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
catch (Exception)
{
MessageBox.Show(item);
}
Thread.Sleep(1000);
}
}
But When second server goes down.It will give me timeout error for third server.
Please check the code and let me know what is wrong with this code.
Probably some kind of connection pooling, HTTP pipelining or keep-alive. This is the wrong approach in the first place.
Connect directly to the right IP (WebRequest.Create("https://1.1.1.1")). If you need to send a Host header add that manually to the request.
I am searching something replacement of System.Net.Sockets.AddressFamily.InterNetwork. I found HostName but unable to find something that can do like AdressFamily does. Actually, I am converting following code in winRT. I know winRT supports Windows.Networking.Sockets etc. Please describe some solution.
The code is,
if (System.Net.Sockets.AddressFamily.InterNetwork == _address.AddressFamily && _address.AddressFamily == address.AddressFamily)
{
long longLocal = BitConverter.ToInt32(_address.GetAddressBytes(), 0);
long longNetMask = BitConverter.ToInt32(_netmask.GetAddressBytes(), 0);
long longRemote = BitConverter.ToInt32(address.GetAddressBytes(), 0);
}
_address is also IPAdress
Well AddressFamily does not directly supports WinRT/Metro project so what you need to do is check the ipAddress information like this
using Windows.Networking;
using Windows.Networking.Sockets;
HostName serverHost = new HostName("www.contoso.com");
StreamSocket clientSocket = new Windows.Networking.Sockets.StreamSocket();
// Try to connect to the remote host
await clientSocket.ConnectAsync(serverHost, "http");
var ipAddress = clientSocket.Information.RemoteAddress.DisplayName
To check your condition use _address.Type == HostNameType.Ipv4 then do something but make sure that GetAddressBytes do not exist in HostName class so for that you need to write your own function to convert an ipAddress into bytes.
I am making an application to make connection through SSH with my server using Routrek Granados library in C#.
I have done almost every thing. but not getting the way that how to receive response/data from the server.
does anyone knows?
please tell me, i shall be very thankful to you.
sample piece of code is here
var param=new SSHConnectionParameter();
param.UserName = "username";
param.Password = "password";
param.Protocol=SSHProtocol.SSH2;
param.AuthenticationType=AuthenticationType.Password;
param.PreferableCipherAlgorithms=new CipherAlgorithm[]{CipherAlgorithm.Blowfish, CipherAlgorithm.TripleDES, CipherAlgorithm.AES128, };
param.WindowSize = 0x1000;
var reader = new Reader();
var sock=new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
sock.Connect(new IPEndPoint(IPAddress.Parse("ip address"),(port number)));
_conn = SSHConnection.Connect(param, reader, sock);
reader._conn = _conn;
SSHChannel ch = _conn.OpenShell(reader);
reader._pf = ch;
SSHConnectionInfo info = _conn.ConnectionInfo;
In your reader class on method OnData the response that comes back you need to set to a public property and then at the end of your code up there check reader.new property. Note that this is all asynchronous so you may need to wait I recommend a waitsignal. I have complete code if needed.
I have implemented the ability to upload, download, delete, etc. using the FtpWebRequest class in C#. That is fairly straight forward.
What I need to do now is support sending arbitrary FTP commands such as
quote SITE LRECL=132 RECFM=FB
or
quote SYST
Here's an example configuration straight from our app.config:
<!-- The following commands will be executed before any uploads occur -->
<extraCommands>
<command>quote SITE LRECL=132 RECFM=FB</command>
</extraCommands>
I'm still researching how to do this using FtpWebRequest. I'll probably try WebClient class next. Anyone can point me in the right direction quicker? Thanks!
UPDATE:
I've come to that same conclusion, as of .NET Framework 3.5 FtpWebRequest doesn't support anything except what's in WebRequestMethods.Ftp.*. I'll try a third party app recommended by some of the other posts. Thanks for the help!
I don't think it can be done with FtpWebRequest... The only way to specify a FTP command is through the Method property, and the documentation states :
Note that the strings defined in the WebRequestMethods.Ftp class are the only supported options for the Method property. Setting the Method property to any other value will result in an ArgumentException exception.
SITE and SYST are not among the predefined options, so I guess you're stuck...
Don't waste time to try the WebClient class, it will give you even less flexibility than FtpWebRequest.
However, there are plenty of third-party FTP implementation, open source or commercial, and I'm pretty sure some of them can handle custom commands...
The FtpWebRequest won't help you as Thomas Levesque has said in his answer. You can use some third party solutions or the following, simplified TcpClient based code which I have refactored from an answer written in Visual Basic:
public static void SendFtpCommand()
{
var serverName = "[FTP_SERVER_NAME]";
var port = 21;
var userName = "[FTP_USER_NAME]";
var password = "[FTP_PASSWORD]"
var command = "SITE CHMOD 755 [FTP_FILE_PATH]";
var tcpClient = new TcpClient();
try
{
tcpClient.Connect(serverName, port);
Flush(tcpClient);
var response = TransmitCommand(tcpClient, "user " + userName);
if (response.IndexOf("331", StringComparison.OrdinalIgnoreCase) < 0)
throw new Exception(string.Format("Error \"{0}\" while sending user name \"{1}\".", response, userName));
response = TransmitCommand(tcpClient, "pass " + password);
if (response.IndexOf("230", StringComparison.OrdinalIgnoreCase) < 0)
throw new Exception(string.Format("Error \"{0}\" while sending password.", response));
response = TransmitCommand(tcpClient, command);
if (response.IndexOf("200", StringComparison.OrdinalIgnoreCase) < 0)
throw new Exception(string.Format("Error \"{0}\" while sending command \"{1}\".", response, command));
}
finally
{
if (tcpClient.Connected)
tcpClient.Close();
}
}
private static string TransmitCommand(TcpClient tcpClient, string cmd)
{
var networkStream = tcpClient.GetStream();
if (!networkStream.CanWrite || !networkStream.CanRead)
return string.Empty;
var sendBytes = Encoding.ASCII.GetBytes(cmd + "\r\n");
networkStream.Write(sendBytes, 0, sendBytes.Length);
var streamReader = new StreamReader(networkStream);
return streamReader.ReadLine();
}
private static string Flush(TcpClient tcpClient)
{
try
{
var networkStream = tcpClient.GetStream();
if (!networkStream.CanWrite || !networkStream.CanRead)
return string.Empty;
var receiveBytes = new byte[tcpClient.ReceiveBufferSize];
networkStream.ReadTimeout = 10000;
networkStream.Read(receiveBytes, 0, tcpClient.ReceiveBufferSize);
return Encoding.ASCII.GetString(receiveBytes);
}
catch
{
// Ignore all irrelevant exceptions
}
return string.Empty;
}
You can expect the following flow while getting through the FTP:
220 (vsFTPd 2.2.2)
user [FTP_USER_NAME]
331 Please specify the password.
pass [FTP_PASSWORD]
230 Login successful.
SITE CHMOD 755 [FTP_FILE_PATH]
200 SITE CHMOD command ok.
You can try our Rebex FTP component:
// create client and connect
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// send SITE command
// note that QUOTE and SITE are ommited. QUOTE is command line ftp syntax only.
client.Site("LRECL=132 RECFM=FB");
// send SYST command
client.SendCommand("SYST");
FtpResponse response = client.ReadResponse();
if (response.Group != 2)
; // handle error
// disconnect
client.Disconnect();
Use sendCommand("SITE LRECL=242 BLKSIZE=0 RECFM=FB");