Xamarin.Android TcpClient not working sometimes - c#

I'm trying to create an application where I have to use WHOIS to get some information I need.
To get the WHOIS information I use this function I found on here and adjusted a little:
string Whois(string domain, string whoisServer = "whois.iana.org")
{
string toReturn = "";
TcpClient tcpClinetWhois = new TcpClient(whoisServer, 43);
MemoryStream memoryStreamWhois = new MemoryStream();
Task copying = tcpClinetWhois.GetStream().CopyToAsync(memoryStreamWhois);
StreamWriter streamWriter = new StreamWriter(tcpClinetWhois.GetStream());
streamWriter.WriteLine(domain);
streamWriter.Flush();
copying.Wait(3000);
toReturn = Encoding.ASCII.GetString(memoryStreamWhois.ToArray());
if (toReturn.Contains("refer:"))
{
toReturn = Whois(domain, toReturn.Split('\n').Where(W => W.StartsWith("refer:")).Select(R => R.Replace("refer:", "").Trim()).First());
}
return toReturn;
}
When I run it, it works for most TLDs like .com or .org but not for .co.uk or .network and probably others too. I have no idea why it wouldn't work because the right WHOIS server gets selected for the TLD. I am also not getting any errors.
I'm using .Net7.0 and my Android 11 phone for testing.
I've tested this exact same function with the exact same domains on the same network but in a Console Application with no problems at all! Everything works fine except when I try this function in a Xamarin Application.

Related

Best way to stream low latency video from a Raspberry Pi to an UWP-APP

For a project, I have to communicate with a Raspberry Pi Zero from a UWP-APP via TCP. Because both, the Raspberry and the computer with the interface, have got a private IP, I have to use a server to forward messages from one client to the other one. This part already works but now my problem is that I have to implement video streaming from the Raspberry to the UWP-APP.
Because my partner is in charge of creating and designing the UWP-APP, I have made myself a little Test-Interface with WindowsForms. I have tried several techniques like Netcat the video output over the server to the client or direct TCP-streaming with raspivid, but the best solution so far is the one I found in this project here. But instead of using the Eneter.Messaging-library I use my own class for communication with TcpClients.
I use mono to run my C# script on the Raspberry and the code to stream the Video looks like this:
while (true)
{
//Wait with streaming until the Interface is connected
while (!RemoteDeviceConnected || VideoStreamPaused)
{
Thread.Sleep(500);
}
//Check if Raspivid-Process is already running
if(!Array.Exists(Process.GetProcesses(), p => p.ProcessName.Contains("raspivid")))
raspivid.Start();
Thread.Sleep(2000);
VideoData = new byte[VideoDataLength];
try
{
while (await raspivid.StandardOutput.BaseStream.ReadAsync(VideoData, 0, VideoDataLength) != -1 && !VideoChannelToken.IsCancellationRequested && RemoteDeviceConnected && !VideoStreamPaused)
{
// Send captured data to connected clients.
VideoConnection.SendByteArray(VideoData, VideoDataLength);
}
raspivid.Kill();
Console.WriteLine("Raspivid killed");
}
catch(ObjectDisposedException)
{
}
}
Basically, this method just reads the h264 data from the Standard-Output-Stream of the raspivid process in chunks and sends it to the server.
The next method runs on the server and just forwards the byte array to the connected interface-client.
while (RCVVideo[id].Connected)
{
await RCVVideo[id].stream.ReadAsync(VideoData, 0, VideoDataLength);
if (IFVideo[id] != null && IFVideo[id].Connected == true)
{
IFVideo[id].SendByteArray(VideoData, VideoDataLength);
}
}
SendByteArray() uses the NetworkStream.Write() Method.
On the interface, I write the received byte[] to a named pipe, to which the VLC-Control connects to:
while (VideoConnection.Connected)
{
await VideoConnection.stream.ReadAsync(VideoData, 0, VideoDataLength);
if(VideoPipe.IsConnected)
{
VideoPipe.Write(VideoData, 0, VideoDataLength);
}
}
Following code initializes the pipe-server:
// Open pipe that will be read by VLC.
VideoPipe = new NamedPipeServerStream(#"\raspipipe",
PipeDirection.Out, 1,
PipeTransmissionMode.Byte,
PipeOptions.WriteThrough, 0, 10000);
And for VLC:
LibVLC libVLC = new LibVLC();
videoView1.MediaPlayer = new MediaPlayer(libVLC);
videoView1.MediaPlayer.Play(new Media(libVLC, #"stream/h264://\\\.\pipe\raspipipe", FromType.FromLocation));
videoView1.MediaPlayer.EnableHardwareDecoding = true;
videoView1.MediaPlayer.FileCaching = 0;
videoView1.MediaPlayer.NetworkCaching = 300;
This works fine on the Windowsforms-App and I can get the delay down to 2 or 3 seconds (It should be better in the end but it is acceptable). But on the UWP-App I can't get it to work even after adding /LOCAL/ to the pipe name. It shows that the VLC-Control connects to the pipe, and I can see that data is written to the pipe but it doesn't display video.
So my question is:
How can I get this to work with the VLC-Control (LibVLCSharp) in UWP? Am I missing something fundamental?
Or is there even a better way to stream the video in this case?
I have researched a bit on the UWP-MediaPlayerElement to but I can't find a way to get my byte[] into it.
First of all, thank you for your quick responses and interesting ideas!
I took a look into Desktop Bridge but it is not really what I wanted, because my colleague has already put in a lot of effort to design the UWP-APP and my Windows-Form is just a botch to try things out.
But the thing that really worked for me was StreamMediaInput . I have no idea how I missed this before. This way I just passed my NetworkStream directly to the MediaPlayer without using a Named-Pipe.
LibVLC libVLC = new LibVLC();
videoView1.MediaPlayer = new MediaPlayer(libVLC);
Media streamMedia = new Media(libVLC, new StreamMediaInput(Client.Channels.VideoConnection.stream), ":demux=h264");
videoView1.MediaPlayer.EnableHardwareDecoding = true;
videoView1.MediaPlayer.FileCaching = 0;
videoView1.MediaPlayer.NetworkCaching = 500;
videoView1.MediaPlayer.Play(streamMedia);
This solution is now working for me both, in UWP and in Windows-Forms.

Tuespechkin takes a long time to respond, and returns null

I'm currently using in my project TuesPechkin version 2.1.1, and also TuesPechkin.Wkhtmltox.AnyCPU v0.12.4.1
This is some of my code:
byte[] result = null;
try
{
var globalSettings = CreateGlobalSettings(portraitMode);
var objectSettings = CreateObjectSettings(websiteUrl, urlParameters);
var document = new HtmlToPdfDocument
{
GlobalSettings = globalSettings
};
document.Objects.Add(objectSettings);
CreateEventLog.CreateInformationLog("Ready to convert PDF");
result = Converter.Convert(document);
CreateEventLog.CreateInformationLog(result == null
? "Conversion failed using the Pechkin library"
: "PDF conversion finished");
I run this code in 3 different environments:
On my local machine it runs fine and it generates the file in 3 seconds.
On one of my servers (let's call it Server A) it runs fine and it generates the file in 3 seconds.
On the other of my servers (let's call it Server B) it holds for 1min (for some reason I don't understand) during the Converter.Convert part, and after that minute it returns null.
Server A and Server B have the same setup (CPU, RAM, etc)
There's no peak increase on Server B during conversion.
Any suggestions/ideas?
I found what the issue is.
The URL I'm trying to convert is in a Presentation Layer, which is deployed in a separate server. Pechkin converter is in a Business Layer.
In Server A, I can access the URL from the Business Server.
In Server B, I cannot access the URL from the Business Server.
This is probably some firewall exception that needs to be created.
It would be nice though to have TuesPechkin, returning an error saying it cannot access the URL.
It is important to check how you get the convert, dispose issue may cause problem
Just check code form here
public static IConverter GetConverter()
{
lock (Locker)
{
if (converter != null)
{
return converter;
}
var tempFolderDeployment = new TempFolderDeployment();
var winAnyCpuEmbeddedDeployment = new WinAnyCPUEmbeddedDeployment(tempFolderDeployment);
IToolset toolSet;
if (HostingEnvironment.IsHosted)
{
toolSet = new RemotingToolset<PdfToolset>(winAnyCpuEmbeddedDeployment);
}
else
{
toolSet = new PdfToolset(winAnyCpuEmbeddedDeployment);
}
converter = new ThreadSafeConverter(toolSet);
}
return converter;
}

Task hang infinitely when calling .Wait() in kafka-net

I'm currently trying to post messages from a for-loop on a kafka server running on my local machine using the kafka-net library in c# (https://github.com/Jroland/kafka-net), following the example given on the linked repo, my code is the following.
string kafkaServer = "http://" + ip + ":" + port;
Uri uri = new Uri(kafkaServer);
var options = new KafkaOptions(uri);
var router = new BrokerRouter(options);
var client = new Producer(router);
...
foreach(string sumup in LS){
payloadJson["fullPathDataFolder"] = remoteFolder;
payloadJson["globalName"] = GloablName;
payloadJson["name"] = name;
payloadJson["text"] = sumUp + "\n";
payloadJson["type"] = type;
string payload = payloadJson.ToString();
KafkaNet.Protocol.Message msg = new KafkaNet.Protocol.Message(payload);
client.SendMessageAsync(topic, new List<KafkaNet.Protocol.Message> { msg }).Wait();
}
This code run through the first iteration and i'm able to retrieve the first string from a second machine linked to the same server with a consumer.
Then the code here above remain stuck at the intruction:
client.SendMessageAsync(topic, new List<KafkaNet.Protocol.Message> { msg }).Wait();
If now I remove the .Wait() this code run quite fast but it randomly ignore some of the string i send
What am I missing ?
P.S.
I'v tried also to use Confluent.kafka and i got similar problems
P.P.S.
It's important that this program run sequentially.

CoolUtils TotalPDFPrinterX causes ASP C# site to crash

My company has purchased the CoolUtils TotalPDFPrinterX from https://www.coolutils.com/TotalPDFPrinterX
I make an HTTP PUT from Postman to the API and I get “Could not get any response”.
When running on my Windows machine the PDF prints fine however on the server the site crashes and in the event log I get the error "A process serving application pool '[MY_APP_POOL]' failed to respond to a ping. The process id was '[MY_PROCESS_ID]'."
Here is my C# code:
PDFPrinterX ppx = new PDFPrinterX();
ppx.Print(fileName, printerName, "-ap Default");
if (ppx.ErrorMessage != null)
{
WriteToSQL(id, false, ppx.ErrorMessage, 2);
Console.WriteLine(ppx.ErrorMessage);
}
By writing to the event log I know the site crashes on this line: PDFPrinterX ppx = new PDFPrinterX(); I have also surrounded the above code with a try catch and no exception is thrown. The site still crashes.
Things I have tried:
Uninstalling and Reinstalling the CoolUtils software
Giving EVERYONE Full control to the site folder and the CoolUtils program folder
Creating a C# desktop application using the same code. THIS WORKS FINE ON THE SERVER. It's just the ASP site that crashes.
Does anyone know what might be causing this?
The more I research this thing online the more I'm inclined to say that ActiveX which is the X in PDFPrinterX doesn't seem to work well when hosted in IIS.
I've seen a few forums where they say it works fine when they debug on localhost but when deployed to server is crashes.
...works fine when used inside localhost(Visual studio)
One of their feature pages shows that it requires Win 2000/NT/XP/2003/Vista/7
You should look into whether your server supports ActiveX components that can work in conjunction with IIS.
Looking at one of their other products support page: TotalPDFConverterX:
the following note in my opinion may also apply to TotalPDFPrinterX, given its dependency on ActiveX as well.
Note: Pay attention to some details during installation Total PDF Converter X:
Do not forget to register ActiveX in your web-server account.
Total PDF Converter X supports only Internet Explorer, Mozilla and Firefox browsers.
ActiveX works only with 32-bit internet information server. 64-bit server is not supported. Use command line version instead.
Thanks to #Nkosi I was able to find a workaround.
ActiveX works only with 32-bit internet information server. 64-bit server is not supported. Use command line version instead.
Our IIS server is 64 bit so that is what probably caused the site to hang up.
Buttt... the command line still worked in printing the PDFs on the server.
Client side code (makes the HTTP POST):
private void SendToPrinter(string fileName, string printerName, int id, decimal documentSequence)
{
// use http client to make a POST to the print api
using (var client = new HttpClient())
{
// compile the values string to transfer in POST
// should finish to look something like this:
// C:\print.pdf&PRTFTW_OFIT&ValShip-155320-1
var values = new Dictionary<string, string>
{
{ "", fileName + "&" + printerName + "&ValShip-" + id + "-" + documentSequence},
};
// URL encode the values string
var content = new FormUrlEncodedContent(values);
// make the POST
// DEBUG
var response = client.PostAsync("http://localhost:54339/api/print", content);
// retrieve the response
var responseString = response.Result.ToString();
}
}
Server side code (receives the HTTP POST):
using System;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace api.valbruna.print.Controllers
{
public class PrintController : ApiController
{
// POST api/print
public HttpResponseMessage Post(HttpRequestMessage request)
{
try
{
// parse the content recieved from the client
var content = request.Content.ReadAsStringAsync().Result;
// decode the content, certain characters such as
// '&' get encoded to URL lingo such as '%26'
content = HttpUtility.UrlDecode(content);
// split the string into 3 seperate parts
String[] str = content.Split('&');
// remove the equal sign from the first string
str[0] = str[0].Trim('=');
// compile the arguments command line string
// should finish to look something like this:
// "C:\Program Files (x86)\CoolUtils\Total PDF PrinterX\PDFPrinterX.exe" "C:\print.pdf" -p"\\PRINTERS\PRTFTW_OFIT" -ap Default -log "C:\inetpub\logs\CoolUtils\log-ValShip-155320-4.txt" -verbosity detail"
String arguments = "\"" + str[0] + "\" -p\"\\\\PRINTERS\\" + str[1] +
"\" -ap Default -log \"C:\\inetpub\\logs\\CoolUtils\\log-" + str[2] +
".txt\" -verbosity detail";
// file location for PDFPrinterX.exe
String file = #"C:\Program Files (x86)\CoolUtils\Total PDF PrinterX\PDFPrinterX.exe";
// start the process
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = file;
startInfo.Arguments = arguments;
process.StartInfo = startInfo;
process.Start();
return new HttpResponseMessage() { Content = new StringContent(content) };
}
catch (Exception e)
{
return new HttpResponseMessage() { Content = new StringContent(e.Message) };
}
}
}
}

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