Check Load Balancing server using C# - c#

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.

Related

C# - Detect public ip adress change, VPN issue

With following code I am able to track public IP changes of my desktop application. This should be able to track if either the public IP changed or the user enabled a VPN to change his public IP. This code is run on application launch and used once again when a check is needed:
public class PublicIP
{
IPAddress last_ip=null;
DateTime timestamp_lastipchange;
public void UpdateIP()
{
List<string> hosts = new List<string>()
{
"https://api.ipify.org",
"https://ipinfo.io/ip",
"https://checkip.amazonaws.com",
"https://wtfismyip.com/text",
"http://icanhazip.com"
};
using(WebClient webclient = new WebClient())
{
foreach(string host in hosts)
{
//Download each string from hosts until an IP could be fetched
try{
var newip = IPAddress.Parse(webclient.DownloadString(service)); //Downloading the string
if(!newip.IsEqual(last_ip) && last_ip!=null) timestamp_lastipchange = DateTime.Now; //Check if the ip changed, if the last known ip does not exists skipp this step
last_ip = newip; //Save last known ip
return;
}
catch { }
}
}
}
}
This approach seems to work pretty well, however during UnitTesting some workflows do not fetch a new IP:
IP change by switching networks: change gets successfully detected
IP changed by provider: change gets successfully detected
VPN was enabled when the application was launched and is then turned off:
change gets successfully detected
VPN was disabled on application start and is turned on during runtime:
change does not get detected. Webclient.DownloadString() still returns the same IP as if the VPN was not enabled.
I am not really sure what is happening in workflow nr 4. Do I have to manually select the new network interface (VPN)? Or is this a caching problem on the client/server side?
WebClient is high-level and might using static pool behind-the-scene (and also deprecated). You might try using HttpClient instead, because HttpClient handle connection via its message handler, and the default one is not static, which means this should work:
using(var httpClient = new HttpClient())
{
var newip = IPAddress.Parse(webclient.GetStringAsync(service)
.ConfigureAwait(false).GetAwaiter().GetResult());
// ...
}

Exception with many iterations in webrequest

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.

Sending Email to SpecifiedPickupDirectory with MailKit

I was using SmtpClient till now with ASP.NET MVC 5. For testing email send functionality on local system, I was using client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
Now, I want to do the same things in ASP.NET Core which does not have SmtpClient class implemented till now. All search for this ended up on MailKit. I have used their send mail code which is working fine with gmail.
I do not want to send testing emails each time and there may be a lot of scenarios in my project where I need to send email. How can I use the local email sending functionality with MailKit. Any links or little source code will help. Thanks
I'm not sure on the finer details of how SmtpDeliveryMethod.SpecifiedPickupDirectory works and what it does exactly, but I suspect it might just save the message in a directory where the local Exchange server periodically checks for mail to send out.
Assuming that's the case, you could do something like this:
public static void SaveToPickupDirectory (MimeMessage message, string pickupDirectory)
{
do {
// Generate a random file name to save the message to.
var path = Path.Combine (pickupDirectory, Guid.NewGuid ().ToString () + ".eml");
Stream stream;
try {
// Attempt to create the new file.
stream = File.Open (path, FileMode.CreateNew);
} catch (IOException) {
// If the file already exists, try again with a new Guid.
if (File.Exists (path))
continue;
// Otherwise, fail immediately since it probably means that there is
// no graceful way to recover from this error.
throw;
}
try {
using (stream) {
// IIS pickup directories expect the message to be "byte-stuffed"
// which means that lines beginning with "." need to be escaped
// by adding an extra "." to the beginning of the line.
//
// Use an SmtpDataFilter "byte-stuff" the message as it is written
// to the file stream. This is the same process that an SmtpClient
// would use when sending the message in a `DATA` command.
using (var filtered = new FilteredStream (stream)) {
filtered.Add (new SmtpDataFilter ());
// Make sure to write the message in DOS (<CR><LF>) format.
var options = FormatOptions.Default.Clone ();
options.NewLineFormat = NewLineFormat.Dos;
message.WriteTo (options, filtered);
filtered.Flush ();
return;
}
}
} catch {
// An exception here probably means that the disk is full.
//
// Delete the file that was created above so that incomplete files are not
// left behind for IIS to send accidentally.
File.Delete (path);
throw;
}
} while (true);
}
The above code snippet uses Guid.NewGuid () as a way of generating a temporary filename, but you can use whatever method you want (e.g. you could also opt to use message.MessageId + ".eml").
Based on Microsoft's referencesource, when SpecifiedPickupDirectory is used, they actually also use Guid.NewGuid ().ToString () + ".eml", so that's probably the way to go.

how can I make a socket connection non-locally?

I tried to search for similar questions but I couldn't since I don't know how to pronounce this question.
My server codes for connection is...
server_Listener = new TcpListener(7778);
server_Listener.Start();
while (true)
{UserSocket user = new UserSocket();
try
{
user.client = server_Listener.AcceptSocket();
}
catch
{
break;
}
if (user.client.Connected)
{
user.server_isClientOnline = true;
this.BeginInvoke((MethodInvoker)(delegate()
{
textBox1.AppendText("client connected\n");
}));
user.server_netStream = new NetworkStream(user.client);
the UserSocket class has a Socket(variable name client), and a netStream (server_netStream) to get to receive and send packet data from clients.
My Question is, this works just fine on local connections, but it doesn't work non-locally.
I tried to access to this server using my laptop, and my friend's, but non of them worked.
Not an error although... but it just couldn't receive the connection.
Are my codes wrong? or are there a new way of getting connection non-locally?
It could be the firewall on your machine or some other issue on your network. You might want to try Wireshark (http://www.wireshark.org/) and see if you can glean any information that way.

Top level domain ignorance at using RIPE

I'm developing a simple app in c#, that can check if a domain name is available to puchase for a specific tld.
The method: I downloaded a whois-server list, I send the domain name to its whois server with a TCP client on the protocol 43, and check the servers answer.
The problem: more countries has the same whois server: "whois.ripe.net" .
If I send the full domain name(with tld), the server's answer is always "No entries found in source RIPE.". If I send the domain name without tld, I dont get any tld specific data about the status of the domain name.
The method I use:
private string GetWhoisInformation(string whoisServer, string url)
{
try
{
StringBuilder stringBuilderResult = new StringBuilder();
TcpClient tcpClinetWhois = new TcpClient(whoisServer, 43);
NetworkStream networkStreamWhois = tcpClinetWhois.GetStream();
BufferedStream bufferedStreamWhois = new BufferedStream(networkStreamWhois);
StreamWriter streamWriter = new StreamWriter(bufferedStreamWhois);
streamWriter.WriteLine(url);
streamWriter.Flush();
StreamReader streamReaderReceive = new StreamReader(bufferedStreamWhois);
while (!streamReaderReceive.EndOfStream)
stringBuilderResult.AppendLine(streamReaderReceive.ReadLine());
return stringBuilderResult.ToString();
}
catch
{
return "lekérdezés sikertelen";
}
}
Example:
I do:
GetWhoisInformation("whois.ripe.net", "pokerstars.hu")
The server's answer:
%ERROR:101: no entries found
%
% No entries found in source RIPE.
for the next command:
GetWhoisInformation("whois.ripe.net", "pokerstars")
the result contains several blocks like this:
% Information related to '80.65.254.128 - 80.65.254.159'
inetnum: 80.65.254.128 - 80.65.254.159
netname: Pokerstars
descr: Hosting
country: GB
admin-c: DC77-RIPE
tech-c: JM2352-RIPE
status: assigned PA
mnt-by: manx-telecom-mnt
changed: bill.hogg#manx-telecom.com 20101123
source: RIPE
There's no information about the domain name "pokerstars.hu". Of course, I get exactly the same answers if I want to check pokerstars.va. Pokerstars.hu is a registred domain, pokerstars.va is not.
How can I find the correct status of a domain name?
RIPE does not serve as a ccTLD whois server for any domains; like ARIN, it contains only netblock information. Each ccTLD has its own root whois server (or, that is, some of them don't have a proper whois service -- for example, the Spanish .es registry requires that you use a web client, with an obnoxious CAPTCHA you have to fill in every time).
See also http://www.ripe.net/data-tools/db although it is not very explicit about what the database does not contain.
You can get the address of the authoritative whois server by requesting the ccTLD's information from whois.iana.org.
vnix$ whois -h whois.iana.org hu | fgrep whois:
whois: whois.nic.hu
See also http://www.iana.org/domains/root/db/
I tried your code against whois.melbourneit.net and it found one of my domains no trouble. I was able to reproduce your problem running against RIPE and so I tried the same query interactively on their website - and had the same result. There's nothing wrong with your code.
tripleee is right about whois.nic.hu, I successfully used it to resolve pokerstars.hu - which leaves me wondering what the blazes is purpose of the RIPE whois server.
Thanks to triplee for showing us how to obtain the whois server friendly-name for a ccTLD.
You may find this useful:
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
namespace Whois
{
class Program
{
static void Main(string[] args)
{
string tldWhoisServer = "whois.iana.org";
string ccTldServer, query = null;
Console.Write("Query> ");
while ((query = Console.ReadLine()) != string.Empty)
{
string tld = query.Substring(query.LastIndexOf('.') + 1);
string foo = GetWhoisInformation(tldWhoisServer, tld);
foo = foo.Remove(0, foo.IndexOf("whois:") + 6).TrimStart();
ccTldServer = foo.Substring(0, foo.IndexOf('\r'));
Console.WriteLine(GetWhoisInformation(ccTldServer, query));
Console.Write("Query> ");
}
}
static string GetWhoisInformation(string whoisServer, string url)
{
try
{
StringBuilder stringBuilderResult = new StringBuilder();
TcpClient tcpClinetWhois = new TcpClient(whoisServer, 43);
NetworkStream networkStreamWhois = tcpClinetWhois.GetStream();
BufferedStream bufferedStreamWhois = new BufferedStream(networkStreamWhois);
StreamWriter streamWriter = new StreamWriter(bufferedStreamWhois);
streamWriter.WriteLine(url);
streamWriter.Flush();
StreamReader streamReaderReceive = new StreamReader(bufferedStreamWhois);
while (!streamReaderReceive.EndOfStream)
stringBuilderResult.AppendLine(streamReaderReceive.ReadLine());
return stringBuilderResult.ToString();
}
catch
{
return "Query failed";
}
}
}
}

Categories

Resources