Disconnect clients on server exit - c#

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.

Related

Setup C# TFTP server using GSF.NET library

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.

Sometime WCF Service stop serving when I press Enter button it allow client apps to communicate

using MyLibrary.Utilities;
using ServerApp.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ServerApp.Managers
{
internal class HostServicesManager
{
private Thread hostServicesThread;
private static ServiceHost examService;
private static ServiceHost authenticationService, timeService;
private static ServiceHost registerService;
private static ServiceHost invigilatorService;
private HostServicesManager() { }
private static HostServicesManager instance = null;
public static HostServicesManager Instance // Singleton Pattern
{
set { instance = value; }
get { if (instance == null) { instance = new HostServicesManager(); } return instance; }
}
public void StartHostServices()
{
hostServicesThread = new Thread(HostServices);
hostServicesThread.Start();
}//end of function
public void StopHostServices()
{
if (hostServicesThread != null)
{
hostServicesThread.Abort();
}
}//end of function
private void HostServices()
{
string myip = Utilities.myIP();
string baseAddress = "http://" + myip + ":" + MyConfiguration.Server_PORT;
if (myip == "")
{
Console.WriteLine("<----------- No network is running on this machine. Connect Registrar with network ----------->");
Console.ReadKey();
return;
}
authenticationService = new ServiceHost(typeof(StudentAuthenticationService), new Uri(baseAddress + "/StudentAuthentication/"));
authenticationService.Open();
registerService = new ServiceHost(typeof(RegisterService), new Uri(baseAddress + "/RegisterService/"));
registerService.Open();
timeService = new ServiceHost(typeof(TimeService), new Uri(baseAddress + "/ServerTimeService/"));
timeService.Open();
examService = new ServiceHost(typeof(PaperService), new Uri(baseAddress + "/ExamService/"));
examService.Open();
invigilatorService = new ServiceHost(typeof(InvigilatorAuthenticationService), new Uri(baseAddress + "/InvigilatorService/"));
invigilatorService.Open();
DisplayServicesStatus();
}
public void DisplayServicesStatus()
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("|------------------Services--------------------|");
Console.WriteLine("| My IP: " + Utilities.myIP() + " Open Port: " + MyConfiguration.Server_PORT + " |"); ;
Console.WriteLine("| 1- Student Authentication Server is running..|");
Console.WriteLine("| 2- Time Service is Running...................|");
Console.WriteLine("| 3- Paper Service is Running..................|");
Console.WriteLine("| 4- Invigilator Service Running...............|");
Console.WriteLine("|______________________________________________|");
Console.WriteLine();
Console.WriteLine("-----------------Services Log-------------------");
Console.BackgroundColor = ConsoleColor.Green;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(Program.uploadPapersInfoList.Count() + " Papers Loaded............");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
}
}
}
WCF Service Stuck
Here is my code. This class manages the different WCF services.
When I run this application, in some cases or on a slow machine the application is stuck and when client apps try to connect with these services, these services do not respond to them. But when I press the Enter button on the console it allows the services to communicate even though it also sends the old responses that it received while it was stuck.
Assuming you don’t have a call to Console.ReadLine() pausing something (which you can check by hitting pause in the debugger and checking the call stack), I would suspect the console is in “quick edit” mode.
When you click or highlight text in quick edit mode, the console will stop, the cursor will change, and the title bar will change until you hit enter (and the selected text will be copied to your clipboard).
See https://superuser.com/questions/1442941/windows-10-console-stops-running-if-i-click-in-the-console-window for a similar scenario

How can I take direct data form Ardruino server and upload to PC another ( installed SQL )

I wrote 2 winforms as follows
Check the connection of the Ardruino to PC 1 and write the received information to log.txt file
Read selected information in log files and send them to PC 2 (SQL installed)
Note: PC 1 has 2 network cards (network card 1 receives the signals of the Arduino over the range: 192.168.1.2; Network card 2 connects to PC 2 via the range: 110.110.1.2)
How do I get the information I need from PC 1 and transfer them to PC 2 (with SQL installed) with only 1 program
My code Winform received form Arduino:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Data.SqlClient;
namespace TCPIPSeverMutilClient
{
public partial class Form1 : Form
{
const int MAX_CONNECTION = 30;
const int PORT_NUMBER =1989;
int currentconnect = 0;
delegate void SetTextCallback(string text);
static TcpListener listener;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IPAddress address = IPAddress.Parse(IPText.Text);
listener = new TcpListener(address, PORT_NUMBER);
AddMsg("Creat Sever with IP :"+ IPText.Text);
AddMsg("Waiting for connection...");
button1.Hide();
listener.Start();
for (int i = 0; i < MAX_CONNECTION; i++)
{
// new Thread(DoWork).Start();
Thread aThread = new Thread(DoWork);
aThread.IsBackground = true; //<-- Set the thread to work in background
aThread.Start();
}
}
private void DoWork()
{
while (true)
{
Socket soc = listener.AcceptSocket();
currentconnect = currentconnect + 1;
SetText("Numbers Connection " + currentconnect.ToString());
Console.WriteLine("Connection received from: {0}", soc.RemoteEndPoint);
try
{
var stream = new NetworkStream(soc);
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
writer.AutoFlush = true;
//writer.WriteLine("Welcome to Student TCP Server");
// writer.WriteLine("Please enter the student id");
while (true)
{
string id = reader.ReadLine();
SetText(id);
// writer.WriteLine("END");
if (String.IsNullOrEmpty(id))
break; // disconnect
//if (_data.ContainsKey(id))
// writer.WriteLine("Student's name: '{0}'", _data[id]);
else
{
writer.WriteLine("END");
// writer.WriteLine("Can't find name for student id '{0}'", id);
}
}
stream.Close();
}
catch (Exception ex)
{
SetText("Error: " + ex);
}
// Console.WriteLine("Client disconnected: {0}",soc.RemoteEndPoint);
soc.Close();
currentconnect = currentconnect - 1;
SetText("Numbers Connection " + currentconnect.ToString());
}
}
private void SetText(string text)
{
if (this.rtbText.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText); // khởi tạo 1 delegate mới gọi đến SetText
this.Invoke(d, new object[] { text });
}
else
{
this.AddMsg(text);
}
}
private void SaveText(string text)
{
const string textFileName = "Log.txt";
const int insertAtLineNumber = 0;
List<string> fileContent = File.ReadAllLines(textFileName).ToList();
// AddMsg(fileContent.Count.ToString());
//fileContent.InsertRange(insertAtLineNumber, text);
fileContent.Insert(insertAtLineNumber, text);
File.WriteAllLines(textFileName, fileContent);
}
private void AddMsg(string msg)
{
rtbText.Items.Add(DateTime.Now + " : " + msg);
SaveText(DateTime.Now + " : " + msg);
if (rtbText.Items.Count >= 150)
{ rtbText.Items.RemoveAt(0); }
}
}
}
As the Arduino card attached to PC 1 cannot be accessed from the PC 2.
You need to pass the Arduino data to the MSSQL Database. Then Retrieve the data in PC 2 by accessing it from PC 1. You can use this Reference for How to access Database over network
Up to now, when I returned this case I had a solution.
In PC1, there are 2 network cards, you just need to use the Network class to find the IP with the IP with IP in PC2
Instead of reading from the log file I was inspired directly from Arduino returned and transmitted to PC2
string hostname = Dns.GetHostName();
System.Net.IPHostEntry ip = new IPHostEntry();
ip = Dns.GetHostByName(hostname);
foreach (IPAddress listip in ip.AddressList)
{
if (listip.ToString().StartsWith("110."))
{
ipMay = listip.ToString();
macPairIp = GetMacByIP(ipMay);
try
{
//Do work here
}
catch (...)
{}
}
}

Display complete SSH shell output including login message and prompt in C#

I'm trying to create a simple SSH client in C#. This is my code now:
using Renci.SshNet;
public static void Main(string[] args)
{
AuthenticationMethod method = new PasswordAuthenticationMethod("pi", "raspberry");
ConnectionInfo connection = new ConnectionInfo("192.168.91.134", "pi", method);
SshClient client = new SshClient(connection);
if (!client.IsConnected)
{
Console.WriteLine("Not Connected...");
client.Connect();
}
while (true)
{
string command = Console.ReadLine();
SshCommand response = client.RunCommand(command);
Console.WriteLine(response.Result);
}
}
Problem:
like this, it shows just the response of the command sent. I would like the entire output, also with the user and the current directory (like a classic SSH shell).
if I want to launch the sudo su command giving the password it doesn't work...
(in the future I want to add the output to a listbox and take the input from a texbox in a winForms app)
Thank you in advance for your help
This is my implementation:
using System;
using System.Threading;
using Renci.SshNet;
public class Program
{
public static void Main(string[] args)
{
SshClient sshClient = new SshClient("192.168.91.134", 22, "pi", "raspberry");
sshClient.ConnectionInfo.Timeout = TimeSpan.FromSeconds(120);
sshClient.Connect();
ShellStream shellStreamSSH = sshClient.CreateShellStream("vt-100", 80, 60, 800, 600, 65536);
Thread thread = new Thread(() => recvSSHData(shellStreamSSH));
thread.Start();
while (true)
{
string command = Console.ReadLine();
shellStreamSSH.Write(command + "\n");
shellStreamSSH.Flush();
}
}
public static void recvSSHData(ShellStream shellStreamSSH)
{
while (true)
{
try
{
if (shellStreamSSH != null && shellStreamSSH.DataAvailable)
{
string strData = shellStreamSSH.Read();
Console.WriteLine(strData);
}
}
catch
{
}
System.Threading.Thread.Sleep(200);
}
}
}
In you want to implement an SSH terminal client (like PuTTY), you need to use SSH "shell" channel.
In SSH.NET, use SshClient.CreateShell or SshClient.CreateShellStream, not SshClient.RunCommand.

SignalR console app start must be called before data can be sent

I am trying to create a client signalr app. At present, I am able to get my MVC clients to send messages to and from the Hub, however, I'm facing some difficulties with my .NET client app
Server Hub code:
namespace ServerHub
{
public class ChatterBox : Hub
{
public void Send(string message)
{
Clients.All.addMessage(message);
}
}
}
Console App code (almost directly lifted from github)
using Microsoft.AspNet.SignalR.Client.Hubs;
using ServerHub;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Say("hello from console");
}
public static void Say(string message)
{
//var connection = new HubConnection("http://localhost/");
//IHubProxy myHub = connection.CreateHubProxy("ChatterBox");
var connection = new HubConnection("http://localhost/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("ChatterBox");
//Start connection
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Failed to start: {0}", task.Exception.GetBaseException());
}
else
{
Console.WriteLine("Success! Connected with client connection id {0}", connection.ConnectionId);
// Do more stuff here
}
});
connection.Send("Hello").ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Send failed {0}", task.Exception.GetBaseException());
}
else
{
Console.WriteLine("Success");
}
});
}
}
}
I get the error message below, during connection.Send()
Start must be called before data can be sent.
Where did I go wrong?
EDIT:
2nd attempt:
var connection = new HubConnection("http://localhost/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("ChatterBox");
//Start connection
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Failed to start: {0}", task.Exception.GetBaseException());
}
else
{
Console.WriteLine("Success! Connected with client connection id {0}",
connection.ConnectionId);
// Do more stuff here
connection.Send("Hello");
}
});
myHub.Invoke("Send", "lol");
Still gives me an error
EDIT: 3rd Attempt
var connection = new HubConnection("http://localhost:60610/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("ChatterBox");
//Start connection
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Failed to start: {0}", task.Exception.GetBaseException());
}
else
{
//Console.WriteLine("Success! Connected with client connection id {0}", connection.ConnectionId);
myHub.Invoke("Send", "lol");
}
});
Seems to be working
I also needed to set the port number - e.g., if I'm browsing my MVC website like this: http://localhost:60610/, this is the address I need to set in my console app.
Can I say that during deployment, it won't be an issue because it'll be port 80 by default?
Read this http://msdn.microsoft.com/en-us/library/dd460717.aspx
TL;DR Start is async and that's not how you write sequential asynchronous code:
var connection = new HubConnection("http://localhost/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("ChatterBox");
//Start connection
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Failed to start: {0}", task.Exception.GetBaseException());
}
else
{
Console.WriteLine("Success! Connected with client connection id {0}", connection.ConnectionId);
// Do more stuff here
connection.Send("Hello").ContinueWith(task =>
{
.......
});
}
});
If you can use .NET 4.5 it'll make your life alot easier:
var connection = new HubConnection("http://localhost/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("ChatterBox");
//Start connection
try
{
await connection.Start();
Console.WriteLine("Success! Connected with client connection id {0}", connection.ConnectionId);
}
catch(Exception ex)
{
Console.WriteLine("Failed to start: {0}", ex.GetBaseException());
}
await connection.Send("Hello");
UPDATE: Let's try this again. The code below will work but you should really read that link to learn how to write async code. Otherwise you'll just run into these problems over and over.
var connection = new HubConnection("http://localhost/");
//Make proxy to hub based on hub name on server
var myHub = connection.CreateHubProxy("ChatterBox");
//Start connection
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
Console.WriteLine("Failed to start: {0}", task.Exception.GetBaseException());
}
else
{
Console.WriteLine("Success! Connected with client connection id {0}",
connection.ConnectionId);
myHub.Invoke("Send", "lol");
}
});

Categories