Setup C# TFTP server using GSF.NET library - c#

I am trying to setup a TFTP server in C#. I am using this library https://www.gridprotectionalliance.org/NightlyBuilds/GridSolutionsFramework/Help/html/N_GSF_Net_TFtp.htm.
using GSF.Net.TFtp;
using System.Net;
IPAddress ip = IPAddress.Parse("192.168.1.102");
TFtpServer tftpserver = new TFtpServer(ip);
tftpserver.Start();
When I run that code the program exits inmediately. It seems I need to listen to an event to do something.
D:\TFTPtest\TFTPtest\bin\Release\net6.0\TFTPtest.exe (process 17884) exited with code 0.
Press any key to close this window . . .
The API says:
public delegate void TFtpServerEventHandler(
ITFtpTransfer transfer,
EndPoint client
)
The API don't give examples on how to do that.
An example of how to do that, how to setup the eventhandler, would be great.
PS: I am a beginner in C#.

I figured out how to handle the events:
using GSF.Net.TFtp;
using System.Net;
namespace Tftp.Net.SampleServer
{
class Program
{
private static String? ServerDirectory;
static void Main(string[] args) {
ServerDirectory = "D:\\Prgramacion\\Tftproot";
TFtpServer tftpserver = new TFtpServer();
Console.WriteLine(tftpserver.ToString());
tftpserver.OnReadRequest += new TFtpServerEventHandler(server_OnReadRequest);
tftpserver.Start();
Console.Read();
}
static void server_OnReadRequest(ITFtpTransfer transfer, EndPoint client)
{
Console.WriteLine("Reading...");
String path = Path.Combine(ServerDirectory, transfer.Filename);
FileInfo file = new FileInfo(path);
//Is the file within the server directory?
if (!file.FullName.StartsWith(ServerDirectory, StringComparison.InvariantCultureIgnoreCase))
{
CancelTransfer(transfer, TFtpErrorPacket.AccessViolation);
}
else if (!file.Exists)
{
CancelTransfer(transfer, TFtpErrorPacket.FileNotFound);
}
else
{
OutputTransferStatus(transfer, "Accepting request from " + client);
StartTransfer(transfer, new FileStream(file.FullName, FileMode.Open, FileAccess.Read));
}
}
private static void StartTransfer(ITFtpTransfer transfer, Stream stream)
{
transfer.OnProgress += new TFtpProgressHandler(transfer_OnProgress);
transfer.Start(stream);
}
static void transfer_OnProgress(ITFtpTransfer transfer, TFtpTransferProgress progress)
{
OutputTransferStatus(transfer, "Progress " + progress);
}
private static void CancelTransfer(ITFtpTransfer transfer, TFtpErrorPacket reason)
{
OutputTransferStatus(transfer, "Cancelling transfer: " + reason.ErrorMessage);
transfer.Cancel(reason);
}
static void transfer_OnError(ITFtpTransfer transfer, TftpTransferError error)
{
OutputTransferStatus(transfer, "Error: " + error);
}
static void transfer_OnFinished(ITFtpTransfer transfer)
{
OutputTransferStatus(transfer, "Finished");
}
static void transfer_OnProgress(ITFtpTransfer transfer, TftpTransferProgress progress)
{
OutputTransferStatus(transfer, "Progress " + progress);
}
private static void OutputTransferStatus(ITFtpTransfer transfer, string message)
{
Console.WriteLine("[" + transfer.Filename + "] " + message);
}
}
}
This was based in the example of another library:
https://github.com/Callisto82/tftp.net/blob/master/Tftp.Net.SampleServer/Program.cs
Edit: I added the full code for reading a file from a TFTP Client.

Related

Having Issues Using WebClient to Download Files In Unity

So I am having a big issue when coding for Unity. I am very new to C# and so have used examples I have found online to make this code. My only issue is there are no errors popping up but it won't download the file properly.
I am using this code so that it will be easy for my users to import unitypackages they would use often. I have a button that works as intended, it shows download and then changes to import if the file exists. However, if I click it when it says download it will instantly say "Download Complete" and the file won't show up for a few minutes. When it finally does the file is 0KB in size.
I really need help figured out why my file isn't downloading properly. I am super stumped.
This code is the script for the WebClient.
using UnityEngine;
using System.IO;
using System.Net;
using System;
using System.ComponentModel;
using UnityEditor;
namespace SentinelsSDK
{
public class SentinelsSDK_ImportManager
{
private static string localPath = "Assets/VRCSDK/Dependencies/VRChat/Imports/";
private static string localDownloadPath = "Assets/VRCSDK/Dependencies/VRChat/Imports/";
private static string urlStart = "https://www.sentinels.xyz/uploads/2/0/9/0/20909832/";
public static void DownloadAndImportAssetFromServer(string assetName)
{
if (File.Exists(localDownloadPath + assetName))
{
sentLog(assetName + " exists. Importing it..");
importDownloadedAsset(assetName);
}
else
{
sentLog(assetName + " does not exist. Starting download..");
downloadFile(assetName);
}
}
private static void downloadFile(string assetName)
{
WebClient w = new WebClient();
w.Headers.Set(HttpRequestHeader.UserAgent, "Webkit Gecko wHTTPS (Keep Alive 55)");
w.QueryString.Add("assetName", assetName);
w.DownloadFileCompleted += fileDownloadCompleted;
w.DownloadProgressChanged += fileDownloadProgress;
string url = urlStart + assetName;
w.DownloadFileAsync(new Uri(url), localDownloadPath + assetName);
}
private static void fileDownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
string assetName = ((WebClient)(sender)).QueryString["assetName"];
sentLog("Download of file " + assetName + " completed!");
}
private static void fileDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
sentLog("Progress is at " + e.ProgressPercentage.ToString() + "%");
}
private static void sentLog(string message)
{
Debug.Log("[SentinelsSDK] AssetDownloader: " + message);
}
public static void importAsset(string assetName)
{
AssetDatabase.ImportPackage(localPath + assetName, true);
}
public static void importDownloadedAsset(string assetName)
{
AssetDatabase.ImportPackage(localDownloadPath + assetName, true);
}
}
}
This code is the button calling the download from my other script.
using SentinelsSDK;
...
private static string localDownloadPath = "Assets/VRCSDK/Dependencies/VRChat/Imports/";
...
GUILayout.BeginHorizontal();
if (GUILayout.Button((File.Exists(localDownloadPath + "poiyomitoon.unitypackage") ? "Import" : "Download") + " - Poiyomi Toon"))
{
SentinelsSDK_ImportManager.DownloadAndImportAssetFromServer("poiyomitoon.unitypackage");
}
GUILayout.EndHorizontal();
So I figured out my issue, but I am not sure why it was an issue. Apparently putting "https://" for the urlstart instead of "http://" broke it, despite you being able to download the file normally regardless of the protocol used. If someone can help me figure out why that is I would be grateful!

Unable to start Windows Service if reference is used

I have create a windows service. when i try to start the service, i recieve the error
Windows could not start the Auto Process service on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion.
This is my code
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Timers;
using Drone.Engine; //
namespace Auto
{
public partial class Service1 : ServiceBase
{
static string month = DateTime.Now.ToString("MMM");
private Timer timer = new Timer();
private Dictionary<string, bool> processStatus = new Dictionary<string, bool>();
private Executor worker = new Executor(); //
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
processStatus.Add("start", false);
processStatus.Add("stop", false);
System.Threading.Thread.Sleep(10000);
WriteToFile("Service Started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 2000;
timer.Enabled = true;
}
private void OnElapsedTime(object sender, ElapsedEventArgs e)
{
foreach (var process in processStatus.Where(v => v.Value == false))
{
WriteToFile(process.Key + " Sync Started at " + DateTime.Now);
ChangeProcessStatus(process.Key, true);
worker.Execute(Executor.sender.Navision, process.Key); //
ChangeProcessStatus(process.Key, false);
WriteToFile(process.Key + " Sync Finished at " + DateTime.Now);
}
}
protected override void OnStop()
{
WriteToFile("Service stopped at " + DateTime.Now);
}
private void ChangeProcessStatus(string key, bool status)
{
processStatus[key] = status;
}
public void WriteToFile(string Message)
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\data\\logs";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\data\\logs\\ServiceLog_" + DateTime.Now.Date.Day + " " + month + ".log";
if (!File.Exists(filepath))
{
using (StreamWriter sw = File.CreateText(filepath))
{
sw.WriteLine(Message);
}
}
else
{
using (StreamWriter sw = File.AppendText(filepath))
{
sw.WriteLine(Message);
}
}
}
}
}
But if i remove the lines
using Drone.Engine;
The service is starting successfully. Why am i unable to use it in the service?
The dll is present in the same directory. I have used the release build for installing. Still this issue.
Previously i was using filepaths like
filePath=#"data\log";
This was working fine in my application. But when i reference it to my windows service, i was getting System.IO.DirectoryNotFoundException error.
I changed the filepath to
filepath=AppDomain.CurrentDomain.BaseDirectory + "\\data\\logs";
It worked for both my service and application.

C# - FTP Upload Using UploadFileAsync With Progress on Console

I'm new to C# and I wanted to do an FTP upload with progress showing on console. My code is as below from some help from MSDN examples.
using System;
using System.Net;
using System.IO;
using System.Threading.Tasks;
namespace FTPUpload
{
class FTPClient
{
public void Upload()
{
string localFile = #"D:\Applications\python-3.3.0.msi";
string destPath = "ftp://127.0.0.1/python-3.3.0.msi";
if (File.Exists(localFile))
{
Console.WriteLine(localFile + " exists!");
}
else
{
Console.WriteLine(localFile + " doesn't exists!");
}
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential("Anonymous", "Anonymous");
client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback);
client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadCompleted);
client.UploadFileAsync(new Uri(destPath), localFile);
Console.WriteLine("Upload started");
}
}
public void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e)
{
Console.WriteLine(e.TotalBytesToSend);
}
public void UploadCompleted(object sender, UploadFileCompletedEventArgs e)
{
Console.WriteLine(e.Result);
}
public static void Main(string[] args)
{
FTPClient ftpClient = new FTPClient();
ftpClient.Upload();
}
}
}
I think I have not written it properly and I tried to search in Google can't find any examples with respect to this.
Kindly point me in right direction.
I have seen this but not able to get the point
File is not uploaded to FTP server on some machines when using WebClient.UploadFileAsync
Thanks!

Disconnect clients on server exit

Here's the server code I am using:
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
using System.Collections.Generic;
namespace flar3server
{
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8080/";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
[HubName("flar3hub")]
public class flare3hub : Hub
{
static Dictionary<string, ChatConnection> connections = new Dictionary<string, ChatConnection>();
Dictionary<string, string> registeredUsers = new Dictionary<string, string>()
{
{ "test1", "pass1" },
{ "test2", "pass2" },
};
/*
public string Send(string message)
{
return message;
}
*/
public void Authenticate(string login, string password)
{
Console.WriteLine("Login [" + Context.ConnectionId + "] " + login + ":" + password);
foreach (ChatConnection connection in connections.Values)
{
if (connection.getLogin() == login)
{
Clients.Caller.Action("ERROR: User already logged in.");
return;
}
}
if (!registeredUsers.ContainsKey(login) || registeredUsers[login] != password)
{
Clients.Caller.Action("ERROR: Login attempt failed.");
return;
}
connections[Context.ConnectionId] = new ChatConnection(login);
Clients.Caller.Action("Logged in successfully");
Clients.All.Action(login + " joined the channel.");
}
public void Broadcast(string message)
{
try
{
Clients.All.sendMessage(connections[Context.ConnectionId].getLogin(), message);
}
catch (KeyNotFoundException)
{
Console.WriteLine("Unpaired [" + Context.ConnectionId + "] " + message);
}
}
}
}
}
And here's the client code:
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.AspNet.SignalR.Client;
namespace flar3client_cli
{
internal class flar3client_cli
{
private static void onDisconnected()
{
Console.WriteLine("Remote server closed the connection. Press enter to close the application.");
Console.ReadLine();
System.Environment.Exit(1);
}
private static void Main(string[] args)
{
//Set connection
var connection = new HubConnection("http://localhost:8080/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("flar3hub");
//Start connection
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("There was an error opening the connection:{0}",
task.Exception.GetBaseException());
Console.WriteLine("Press enter to continue...");
Console.ReadLine();
connection.Stop();
System.Environment.Exit(1);
}
else
{
Console.WriteLine("Connected");
}
}).Wait();
connection.Closed += onDisconnected;
myHub.On<string>("Action", param =>
{
Console.WriteLine(param);
});
myHub.On<string>("SendMessage", param =>
{
Console.WriteLine(param);
});
myHub.Invoke<string>("Authenticate", "test1", "pass1").Wait();
while (true)
{
myHub.Invoke<string>("Broadcast", Console.ReadLine()).Wait();
}
How can I make the server disconnect all clients when its application window is closed so that the clients can find that out?
How can I make the server disconnect all clients when its application window is closed so that the clients can find that out?
With your code, clients will find out server is gone but only after disconnect timeout which is the time client is trying to reestablish connection until give up.
You can change timeout value if needed but it is probably better to send "hey, server is going down" message to all clients instead...
First of all, I disabled the x button of the winform. Then I added a start button on the winform to start the signalr server. I also added a stop button, when this stop button is click, I called clients.all.somefunction to tell all the clients that the Server is going to be closed, well this process may takes a few seconds, and I start a timer in the server, say 10 seconds, after 10 seconds, I close the winform! that's how I did it.
but Actually I don't know how to do it with a console server.

C# UDP Chat receive no message

I try to write a UDP-Chat in C#.
I have some unexpected behavoir in my Chat Programm, when I start the programm on two different machines connected to the same Network. At the first mashine the programm works fine it can send and recive messages properly, but on the second machine it can just send messages but it can't recive them.
I testet this with a 3rd mashine too(a VM with a bridged networkinterface), but with the same result, it just can send messages without recieving.
is there a error in my code or is it a desing error?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Net.Sockets;
using System.Net;
using System.Diagnostics;
using System.Threading;
using System.Net.NetworkInformation;
using System.ComponentModel;
using System.Data;
namespace CScharpChat
{
/// <summary>
/// Interaktionslogik für Chat_window.xaml
/// </summary>
public partial class Chat_window : Window
{
string name = "testuser";
UdpClient receiveClient = new UdpClient(1800);
IPEndPoint receiveEndPint = new IPEndPoint(IPAddress.Any, 0);
public Chat_window(string name)
{
this.name = name;
fileWriter("Chat started", false); // write the initial start date in the errorfile
InitializeComponent();
Message_Load(); // starts the listen server theread
}
private void Message_Load()
{
lb_chat.Items.Add(name + " Joined the room...");
Thread rec = new Thread(ReceiveMessageFn);
rec.Start();
}
private void ReceiveMessageFn()
{
try
{
while (true)
{
Byte[] receve = receiveClient.Receive(ref receiveEndPint);
string message = Encoding.UTF8.GetString(receve);
if (message == name + " logged out...")
{
break;
}
else
{
if (message.Contains(name + " says >>"))
{
message = message.Replace(name + " says >>", "Me says >>");
}
ShowMessage(message);
}
}
//Thread.CurrentThread.Abort();
//Application.Current.Shutdown();
}
catch (Exception e)
{
//errorHandler(e);
}
}
private void ShowMessage(string message)
{
if (lb_chat.Dispatcher.CheckAccess())
{
lb_chat.Items.Add(message);// add Item to list-box
lb_chat.ScrollIntoView(lb_chat.Items[lb_chat.Items.Count - 1]);// scroll down to current Item
lb_chat.UpdateLayout();
}
else {
lb_chat.Dispatcher.BeginInvoke(
new Action<string>(ShowMessage), message); // if list-box is not access able get access
return;
}
}
private void tb_eingabe_GotFocus(object sender, RoutedEventArgs e)
{
tb_eingabe.Text = "";
}
private void btn_submit_Click(object sender, RoutedEventArgs e)
{
submit_message();
}
private void tb_eingabe_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
submit_message();
}
}
void submit_message()
{
if (tb_eingabe.Text != "")
{
string data = name + " says >> " + tb_eingabe.Text;
SendMessage(data);
tb_eingabe.Clear(); // clear the textbox-values
tb_eingabe.Focus(); // get focus on tb if the submit button was used, the tb lost the focus
}
}
private void SendMessage(string data)
{
try{
UdpClient sendClient = new UdpClient();
Byte[] message = Encoding.UTF8.GetBytes(data); // use UTF8 for international encoding
IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, 1800); // use a broadcast with the given port
sendClient.Send(message, message.Length, endPoint);
sendClient.Close();
}
catch (Exception e)
{
errorHandler(e);
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
string data = name + " logged out...";
SendMessage(data); // send a logout message to the other chat peers
}
// debugging functions
static void errorHandler(Exception errorMsg)
{
MessageBox.Show(errorMsg.ToString()); // create a error-message-box
fileWriter(errorMsg.ToString(), true); // call the file-writer function to write the error in a file
}
static void fileWriter(string fileText, bool append)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(".\\Errorfile.txt", append); // locate the error next to the chat.exe
file.WriteLine(GetTime(DateTime.Now) + "\n " + fileText); // append the date
file.Close();
}
public static String GetTime(DateTime val)
{
return val.ToString("yyyyMMddHHmmssffff"); // return the current date as string
}
}
}
Instead of IPAddress.Broadcast(255.255.255.255) provide your local network broadcast address. See the example below:
IPAddress broadcast = IPAddress.Parse("192.168.1.255"); //replace the address with your local network.
IPEndPoint endPoint = new IPEndPoint(broadcast, 11000);
sendClient.Send(message, message.Length, endPoint);
IPAddress.Broadcast doesn't work in some network.

Categories