Socket thread exits after disconnect - c#

I build a quick little script to take data from an app I created for my phone and put it in a textbox and it works perfectly with this code:
private void workerVoid()
{
string receivedDataString = null;
listenSock.Listen(3);
acceptedSock = listenSock.Accept();
listenSock.Bind(new IPEndPoint(IPAddress.Any, 5665));
while(shouldRun)
{
while (listenSock.SendBufferSize != 0)
{
Buffer = new byte[listenSock.SendBufferSize];
int byteCount = acceptedSock.Receive(Buffer);
byte[] byteFormatted = new byte[byteCount];
for (int byteCounter = 0; byteCounter < byteCount; byteCounter++)
{
byteFormatted[byteCounter] = Buffer[byteCounter];
}
receivedDataString = Encoding.ASCII.GetString(byteFormatted);
setTextDelegate sTD = new setTextDelegate(setText);
reqFormVar.Invoke(sTD, new object[] { receivedDataString });
}
}
}
With workerVoid being a thread. Again this works perfectly however, when the device that is connected (my phone) disconnects, the thread stops running altogether (I get the thread .. has exited in visual studio) and my device is unable to connect after that, even though I have a while loop that should run forever.
How can I make it so my device can reconnect again after disconnecting without the thread exiting?
Thanks

Your code might throw an exception , causing the while loop to be ignored, to avoid this .
Surround your internal while loop in a try catch , and move deceleration inside the try catch block like so :
var shouldRun = true;
while(shouldRun)
{
try
{
string receivedDataString = null;
listenSock.Listen(3);
acceptedSock = listenSock.Accept();
listenSock.Bind(new IPEndPoint(IPAddress.Any, 5665));
while (listenSock.SendBufferSize != 0)
{
...
}
}
catch
{
}
}

Related

Allow main (gui) thread while doing a task then update table

I'm using a winform to try to gather online/offline status of every IP on the network, doing so I'm using a ping request, if it replies it marks the IP as online then moves on. Only issue is waiting for up to 255 replies, after it gets all 255 responses I am wanting it to fill a data grid view.
I've managed to get it all to work but only downside is, gui hangs while doing this process, I figured just use a separate thread with the following expression
Thread T1 = new Thread(PingHost)
T1.run();
PingHost does as the name implies, pings all the hosts and decides if online or offline. Problem is I tried to update the dgv table from the thread, naturally dgv is locked to main thread.
So I tried switching to a Task and just grab the return value and update after everything is finished. Sadly I can't quite get how to get the return value from the task AND have it run on a separate thread.
I've tried googling different methods, but just running in circles at this point, so I humbly come to you guys for assistance
Code of main thread using tasks
List<string> everything = new List<string>();
int i = 0;
Task<List<string>> task1 = Task<List<string>>.Factory.StartNew(PingHost);
everything = task1.Result;
foreach(var item in everything)
{
var index = dataGridView1.Rows.Add();
dataGridView1.Rows[i].Cells["IP"].Value = item;
i++;
}
And this is the thread of my PingHost method
bool pingable = false;
Ping pinger = null;
int i = 0;
string ip;
while (i < 255)
{
ip = "192.168.0." + i;
try
{
pinger = new Ping();
PingReply reply = pinger.Send(ip, 8);
pingable = reply.Status == IPStatus.Success;
}
catch (PingException)
{
MessageBox.Show("ERROR");
// Discard PingExceptions and return false;
}
finally
{
if (pinger != null)
{
pinger.Dispose();
}
}
if (pingable)
{
checkedIP.Add(ip + ": ONLINE");
}
else
{
checkedIP.Add(ip + ": OFFLINE");
}
i++;
}
return checkedIP;
This might be a bit overkill, but I just drafted a solution. Basically I created a new Class for pinging with an event that triggers after each Ping returned, this event uses custom EventArgs to return the IP that was just pinged and if it is online or not. I then subscribed to that Event in my GUI Thread and just update the GUI. Here's some code:
This is my Pinger class responsible for pinging the actual Computers:
class Pinger
{
public event EventHandler<PingReturnedEventArgs> OnPingReturned;
public void PingNetwork()
{
for (int i = 1; i <= 255; i++)
{
string ip = $"192.168.0.{i}";
Ping ping = new Ping();
try
{
PingReply reply = ping.Send(IPAddress.Parse(ip));
TriggerEvent(reply?.Address.ToString(), true);
}
catch (Exception)
{
TriggerEvent(ip, false);
}
}
}
private void TriggerEvent(string ip, bool online)
{
if (OnPingReturned == null) return;
PingReturnedEventArgs args = new PingReturnedEventArgs(ip, online);
OnPingReturned(this, args);
}
}
My custom EventArgs:
class PingReturnedEventArgs : EventArgs
{
public string Ip { get; private set; }
public bool Online { get; private set; }
private PingReturnedEventArgs() { }
public PingReturnedEventArgs(string ip, bool online)
{
Ip = ip;
Online = online;
}
}
And finally here is how I'm actually using all of this:
Pinger pinger = new Pinger();
pinger.OnPingReturned += Your event handler to update the GUI
// I recommend doing it like this so you can stop the Thread at a later time
// Maybe with like a cancel button
Thread pingThread = new Thread(pinger.PingNetwork);
pingThread.Start();
The event handler looks like this private void PingReturnedHandler(object sender, PingReturnedEventArgs args)
The two main benefits of this are that 1. the GUI Thread remains unblocked, meaning the GUI will still respond to user input and 2. this procedurally (on every ping completion) triggers the event, meaning that if it takes a long time to ping all the PCs you don't have to wait for the entirety to finish before the user sees something

c# renci ssh command output differs from client to client

Something really odd is happening to me.
I have ssh command which executes python script on my remote server.
When I execute it through PuTTY it works like it should and desired output is shown. But when executed through my C# app using ssh.net it always returns some old data that's long time gone from the server (which is freebsd 9.3).
Here's how I execute my command and catch output:
var task = new Task(() => {
var ret = ssh_instance.CreateCommand("cd /home/" + "python python_script.py -param");
ret.Execute();
FlexibleMessageBox.Show(ret.Result);
});
task.Start();
It seems literally unexplainable to me so I would be really thankful if someone could enlighten me what am I doing wrong.
Please remember.
Connection will closed after calling "CreateCommand()" method.
You need to read all of received data from your stream against your each command.
--> In my opinion, this is a reason why you've got old result from your connection.
So, I try to use Renci.SshNet.ShellStream class. in my code was,
private Renci.SshNet.SshClient _client = null;
private Renci.SshNet.ShellStream shellStream = null;
private void connect()
{
try
{
this.disConnect();
_client = new Renci.SshNet.SshClient(cboUri.Text, tbxSrvUsr.Text, tbxSrvPW.Text);
//_client.ErrorOccurred += new EventHandler<Renci.SshNet.Common.ExceptionEventArgs>(_client_ErrorOccurred);
//_client.HostKeyReceived += new EventHandler<Renci.SshNet.Common.HostKeyEventArgs>(_client_HostKeyReceived);
_client.Connect();
byte[] buffer = new byte[1000];
shellStream = _client.CreateShellStream("Jornathan", 80, 24, 800, 800, 1024);
shellStream.BeginRead(buffer, 0, buffer.Length, null, null);
shellStream.DataReceived += new EventHandler<Renci.SshNet.Common.ShellDataEventArgs>(shellStream_DataReceived);
tbxStatus.Text = "Connected";
this.btnConnect.Enabled = false;
this.cboServerList.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
and add method to read all text from server.
Please remember, you should read all text until encounter received data size is "0". refer as below.
private void readOutput()
{
do
{
string strOutput = shellStream.ReadLine();
if (strOutput != null && strOutput.Length > 0)
{
System.Console.WriteLine(strOutput);
this.SetStatusText(strOutput);
}
else
{
break;
}
} while (true);
}
And then add event handler, that's it!.
private System.Threading.Thread Thread_OutputHandle = null;
private void shellStream_DataReceived(object sender, Renci.SshNet.Common.ShellDataEventArgs e)
{
if (Thread_OutputHandle == null)
{
Thread_OutputHandle = new System.Threading.Thread(new System.Threading.ThreadStart(readOutput));
Thread_OutputHandle.Start();
}
else if (Thread_OutputHandle.ThreadState == System.Threading.ThreadState.Stopped)
{
Thread_OutputHandle.Abort();
Thread_OutputHandle = new System.Threading.Thread(new System.Threading.ThreadStart(readOutput));
Thread_OutputHandle.Start();
}
}
Others:
I hope to remember where I've got help to make this code.
but I can't.
Please let me know when you find location of code that I've got help.
I'll add its location to here.

mini210 socket multithread

i do have an embedded board (mini/tiny 210)
and i did try building an application which uses system.socket and system.socket.net in C# ( vs2005 - wince5 device application but i do have wince 6 on my device!! )
my purpose is to send and receive data bytes using Ethernet. for sending , well there is no problem but receive does need multitasking.
i should start a task so it can listen to the port if there is any data upcoming but once i add thread part to my code the whole program crashes (dose not do that in pc x64 core i5) but in embedded board it will crash.
if i eliminate multi tasking i might lose some data when networkstream.read is not online or when networkstream.read is online and i'm waiting for data,which ends in program will not respond up until the timeout. here is some of my codes . hope it helps.
this code does work :
private void button_connect_Click(object sender, EventArgs e)
{
try
{
//Thread TH = new Thread(new ThreadStart(con));
//TH.Start();
con();
}
catch
{
MessageBox.Show("THREAD ERROR");
}
}
public void con()
{
try
{
cli = null;
cli = new TcpClient();
cli.Connect(IPAddress.Parse(textBox_ip.Text),Convert.ToInt32(textBox_port.Text));
st = null;
st = cli.GetStream();
button_connect.Enabled = false;
button_Close.Enabled = false;
button_disconnect.Enabled = true;
statusBar1.Text = "Connected to server";
//Thread rec = new Thread(new ThreadStart(recf));
//rec.Start();
}
catch
{
MessageBox.Show("Connection faild","Error");
statusBar1.Text = "Faild to connect to server";
}
this code dose not work :
private void button_connect_Click(object sender, EventArgs e)
{
try
{
Thread TH = new Thread(new ThreadStart(con));
TH.Start();
//con();
}
catch
{
MessageBox.Show("THREAD ERROR");
}
}
public void con()
{
try
{
cli = null;
cli = new TcpClient();
cli.Connect(IPAddress.Parse(textBox_ip.Text),Convert.ToInt32(textBox_port.Text));
st = null;
st = cli.GetStream();
button_connect.Enabled = false;
button_Close.Enabled = false;
button_disconnect.Enabled = true;
statusBar1.Text = "Connected to server";
//Thread rec = new Thread(new ThreadStart(recf));
//rec.Start();
}
catch
{
MessageBox.Show("Connection faild","Error");
statusBar1.Text = "Faild to connect to server";
}
}
as you can see i'm getting this crash while just one of my task is in the code the second task has been commented
i appreciate your help in advance
The crash is probably caused by updating UI elements from a secondary thread.
The con method reads a textbox and updates several buttons as well as a status bar, and this should only happen on the main application thread.
To verify whether this is the issue, you could simply comment out the lines in the con method that access UI elements (copy the textbox value to a member string before starting the thread, or just hard-code the IP address) and re-run the application.
Then to actually fix the problem you'll have to look into Control.Invoke.

Broadcast from bluetooth server to multiple bluetooth clients with 32feet

I have an issue about the server-client communication.
I googled around but I did not find a solution to this.
Right now I am using 32feet in order to get in touch 2 or more (till 7) BT clients to 1 BT server.
I need to broadcast a message from the server to every device in the same time, but I don't know how to do it.
The only way I figured out was to use the list of connection in order to send the message one per time, but it means a delay between each message sent (around 100 ms per device). Unfortunately it means to have a large delay on the last one.
Can someone please give me an advice on how to solve this problem?
Is there a way to broadcast the message to all devices in the same time?
If it can be helpfull, here there is the handle of connection and reading from devices.
Thanks for your help
private void btnStartServer_Click(object sender, EventArgs e)
{
btnStartClient.Enabled = false;
ConnectAsServer();
}
private void ConnectAsServer()
{
connessioniServer = new List<BluetoothClient>();
// thread handshake
Thread bluetoothConnectionControlThread = new Thread(new ThreadStart(ServerControlThread));
bluetoothConnectionControlThread.IsBackground = true;
bluetoothConnectionControlThread.Start();
// thread connessione
Thread bluetoothServerThread = new Thread(new ThreadStart(ServerConnectThread));
bluetoothServerThread.IsBackground = true;
bluetoothServerThread.Start();
}
private void ServerControlThread()
{
while (true)
{
foreach (BluetoothClient cc in connessioniServer)
{
if (!cc.Connected)
{
connessioniServer.Remove(cc);
break;
}
}
updateConnList();
Thread.Sleep(0);
}
}
Guid mUUID = new Guid("fc5ffc49-00e3-4c8b-9cf1-6b72aad1001a");
private void ServerConnectThread()
{
updateUI("server started");
BluetoothListener blueListener = new BluetoothListener(mUUID);
blueListener.Start();
while (true)
{
BluetoothClient conn = blueListener.AcceptBluetoothClient();
connessioniServer.Add(conn);
Thread appoggio = new Thread(new ParameterizedThreadStart(ThreadAscoltoClient));
appoggio.IsBackground = true;
appoggio.Start(conn);
updateUI(conn.RemoteMachineName+" has connected");
}
}
private void ThreadAscoltoClient(object obj)
{
BluetoothClient clientServer = (BluetoothClient)obj;
Stream streamServer = clientServer.GetStream();
streamServer.ReadTimeout=1000;
while (clientServer.Connected)
{
try
{
int bytesDaLeggere = clientServer.Available;
if (bytesDaLeggere > 0)
{
byte[] bytesLetti = new byte[bytesDaLeggere];
int byteLetti = 0;
while (bytesDaLeggere > 0)
{
int bytesDavveroLetti = streamServer.Read(bytesLetti, byteLetti, bytesDaLeggere);
bytesDaLeggere -= bytesDavveroLetti;
byteLetti += bytesDavveroLetti;
}
updateUI("message sent from "+clientServer.RemoteMachineName+": " + System.Text.Encoding.Default.GetString(bytesLetti));
}
}
catch { }
Thread.Sleep(0);
}
updateUI(clientServer.RemoteMachineName + " has gone");
}
private void updateUI(string message)
{
Func<int> del = delegate()
{
textBox1.AppendText(message + System.Environment.NewLine);
return 0;
};
Invoke(del);
}
private void updateConnList()
{
Func<int> del = delegate()
{
listaSensori.Items.Clear();
foreach (BluetoothClient d in connessioniServer)
{
listaSensori.Items.Add(d.RemoteMachineName);
}
return 0;
};
try
{
Invoke(del);
}
catch { }
}
I don't exactly understand how you do it right now (the italian names are not helping...) but maybe my solution can help you.
first of all, bluetooth classic does not support broadcast. so you have to deliver at one at a time.
i do connect to 7 serial port devices at a time, using 7 threads. then i tell every thread to send data. this is very close to same time, but of course not exactly.
let me know if that helps or if you need a code example.

Multithreading with checking

I wanted to write program that will check proxies... I wanted to use mutlithreading but don`t know really how to apply it to my program:
int ktory = 0;
// Button to start multithreading
private void p_check_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
Thread th = new Thread(test_proxy);
CheckForIllegalCrossThreadCalls = false;
th.Start();
}
}
//This is my function to test proxies
private void test_proxy()
{
try
{
int ile = p_listbox.Items.Count;
string proxy = null;
//'ktory' - means position in listbox
proxy = p_listbox.Items[ktory].ToString();
ktory += 1;
//Splitting on IP and PORT
int gdzie = proxy.IndexOf(":");
string IP = proxy.Remove(gdzie);
string ipp = proxy.Replace(IP + ":", "");
int PORT = Int32.Parse(ipp);
//end o splitting
//My testing of anonimty ( works good don`t need to check)
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(p_proxyjudge.Text);
WebProxy adr_proxy = new WebProxy(IP, PORT);
adr_proxy.UseDefaultCredentials = true;
request.Proxy = adr_proxy;
request.Timeout = 15000;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
// Checking if anonymous ( not important)
StreamReader sr = new StreamReader(stream);
while (sr.EndOfStream != true)
{
string checking = sr.ReadLine();
if (!checking.Contains("REMOTE_ADDR ="))
p_work.Items.Add(proxy);
}
sr.Close();
stream.Close();
}
catch (Exception ex)
{
ktory += 1;
}
}
< To code : ile and ktory are just like i, or j as numerous variable >
But my multithreading stops on 10 first proxies or just checks them 10x times as one...
The main problem is to make 10 bots to check proxies and after finished checking one proxy move onto another at listbox (but still others bots work in background)
PLEASE HELP ME :) I`m sitting 2nd day on it and cannot figure it out
You are not locking around access to ktory, which is being altered by multiple threads. Because of this, there is no guarantee that your 10 threads will check 10 different proxies.
Object _lock = new Object();
int ktory=0;
...
private void test_proxy()
{
try
{
int ile = p_listbox.Items.Count;
string proxy = null;
//'ktory' - means position in listbox
lock (_lock) {
proxy = p_listbox.Items[ktory].ToString();
ktory += 1;
}
...

Categories

Resources