I'm trying to implement Websockets in c# and i tried many ways but nothing works fine.
i) working fine with ClientwebSocket class but this class don't have events(i need events)
ii) tried with WebSocketSharp.WebSocket class but closing immediately after opening connection
iii) WebSocket4Net.WebSocket same problem closing connection immediately
can anyone please help me in solving this issue.A big thanks in advance.
class SocketConnection
{
public static WebSocketSharp.WebSocket client;
public void connectionEstablish()
{
//---------------------------WebSocketSharp ----------------------------
using (client = new WebSocketSharp.WebSocket("ws://localhost:8182"))
{
client.OnClose += new EventHandler<CloseEventArgs>(onClosed);
client.OnMessage += new EventHandler<MessageEventArgs>(onReceived);
client.OnOpen += new EventHandler(OnConnectionOpen);
client.Connect();
}
}
public static void onClosed(object sender, EventArgs e)
{
Console.WriteLine("Inclose");
}
public static void onReceived(object sender, MessageEventArgs e)
{
Console.WriteLine("received");
}
public void OnConnectionOpen(object sender, EventArgs e)
{
Console.WriteLine("opened connection");
}
}
I hope that your issue is with the using in the code. The variable client is an using variable so It will get disposed when using block ends(That is what the purpose of using, calling dispose automatically).
That means after executing the client.Connect(); using block ends and hence the object get disposed. To verify this, try remove the using block and change the code like the following:
var client = new WebSocketSharp.WebSocket("ws://localhost:8182");
Don't forget to dispose the object after use.
Related
I'm using Kellerman .NET SFTP Library and I'm having some issues using event handlers
According to the documentation it has the following events:
I'm interested in two of them:
TransferCompleteEvent
FailureEvent
I would like to display a message when the transfer is complete and restart the upload if connection failed.
In my class I have the following:
public static void uploadToSFTP()
{
try
{
SFTP myConnection = new SFTP();
myConnection.EnableLogging();
myConnection.HostAddress = "servername";
myConnection.UserName = "username";
myConnection.Password = "password";
myConnection.CurrentDirectory = "directory";
myConnection.Connect();
//UPLOADING FILE TO SFTP SERVER
myConnection.UploadFileAsync(yesterdaysZipFile, localZipFileName);
while (myConnection.IsBusy == true)
{
//PRINT HOW LONG REMAINING FROM UPLOAD
Console.WriteLine(myConnection.EstimatedTimeRemaining);
}
//declaring an eventhandler
myConnection.TransferCompleteEvent += SFTPCompleted;
myConnection.Disconnect();
myConnection.Dispose();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
And then I have
public static void SFTPCompleted(Object sender, TransferCompletedEventArgs e)
{
Console.WriteLine("Completed");
}
My problem is in this line:
myConnection.TransferCompleteEvent += SFTPCompleted;
When I use the debugger and get to this line it skips and goes to the next line it never goes to
public static void SFTPCompleted(Object sender, TransferCompletedEventArgs e)
{
Console.WriteLine("Completed");
}
What am I doing wrong here?
And in regards the FailureEvent I can't even get it to compile:
myConnection.FailureEvent += TransferFailed;
Here's the event:
public static void TransferFailed(Object sender, SFTP.FailureEventHandler e)
{
Console.WriteLine("failed");
}
I get this compiler error:
Error 1 No overload for 'TransferFailed' matches delegate 'KellermanSoftware.NetSFtpLibrary.SFTP.FailureEventHandler'
This is my first time using this library. Any suggestion would be helpful.
This line:
myConnection.TransferCompleteEvent += SFTPCompleted;
is attaching an event handler.
You are attaching the event handler after calling UploadFileAsync and waiting for it to stop being busy. At this point, the event would have already fired, so you're missing out on hearing about it.
You should attach the event handler as soon as you create the myConnection object.
SFTP myConnection = new SFTP();
myConnection.TransferCompleteEvent += SFTPCompleted;
Your second problem is that you cannot attach the TransferFailed event. That's because you have the wrong parameters in your handler function. My guess is that it should be:
public static void TransferFailed(Object sender, SFTP.FailurEventArgs e)
Have a look at the SFTP.FailureEventHandler declaration. It will tell you what the parameters need to be.
I had write a little application on c# to reading some plc data by using ethernet protocol. Ethernet socket, open and close are stored inside a .dll library.
Now, i using this public method:
public static string readdata()
{
try
{
...
return (plcdata());
}
catch
{}
}
My doubt: if the plcdata() (that is a method of a .dll) waiting a few second (for istance slow comunication ...) my application may be frozen.
So, i try to add a EventHandler on string returned like this:
private static TextBox auxDataTextBox = new TextBox();
public static void goRead()
{
auxDataTextBox.TextChanged += new EventHandler(auxDataIncoming);
auxDataTextBox.Text = plcdata();
}
private static void auxDataIncoming(object sender, EventArgs e)
{
// Do something
}
In this case when the "plcdata()" changed, the auxDataIncoming will be raise.
It is correct? Or is better make a timeout control? Or make new thread?
Thanks a lot for yours opinion
Your change won't make a difference, it' still all running on the UI thread. To make plcdata() a non-blocking call you would need to fire it off on another thread e.g.
private static TextBox auxDataTextBox = new TextBox();
public static void goRead()
{
auxDataTextBox.TextChanged += new EventHandler(auxDataIncoming);
Task.Factory.StartNew(() => {
return plcData();
}).ContinueWith(task => {
auxDataTextBox.Text = task.Result;
}, null, TaskContinuationOptions.NotOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
}
private static void auxDataIncoming(object sender, EventArgs e)
{
// Do something
}
This will not unfreeze your application. The effect will be exactly the same. This is because you are still running the plcdata on your UI thread.
The whole event structure you set up does not make sense at all.
You should look into multithreading. A very easy way to do this is using a BackgroundWorker.
namespace TinyChat
{
class Program
{
NetConnection Client;
static void Main(string[] args)
{
Program TinyChat_Function = new Program();
TinyChat_Function.connectTinyChat();
}
void connectTinyChat()
{
Client = new NetConnection();
Client.OnConnect += new ConnectHandler(Client_OnConnect);
Client.NetStatus += new NetStatusHandler(Client_NetStatus);
Client.Connect("rtmp://209.212.144.77:443/tinyconf", new string[] { "SomeRoom", "none", "show", "tinychat" });
}
}
Errors:
1 The name 'Client_OnConnect' does not exist in the current context
2 The name 'Client_netStatus' does not exist in the current context
Using latest version of FluorineFx.
The documentation shows that this is the right way to do this, but this does not work. Any ideas on how i can solve this problem?
The documentation can be found here.
Where is the code for the Client_OnConnectevent handler and the Client_NetStatusevent handlers? You are adding the events here in your lines , but you didn't implement the code. Unless you forgot to paste it in the question.
Client.OnConnect += new ConnectHandler(Client_OnConnect);
Client.NetStatus += new NetStatusHandler(Client_NetStatus);
You if you look at the documentation link this is the code
void netConnection_OnConnect(object sender, EventArgs e)
{
//The NetConnection object is connected now
netConnection.Call("serverHelloMsg", new ServerHelloMsgHandler(), "some text");
}
You should replace netConnection_OnConnect to Client_OnConnect and write the code in the method, maybe like this
void Client_OnConnect(object sender, EventArgs e)
{
//handle connection below and do whatever needs to be done
}
I am trying to implement a basic TCP client in WPF. I have managed to to this using windows forms but can't get it working in WPF. I have tried going back to the very basics and adding things bit by bit. This is to connect to an arduino that is outputing single lines of code. I can successfully connect to it through telnet so the problem is with my code.
This is what I have so far:
public partial class MainWindow : Window
{
private TcpClient tcp;
private StreamWriter SwSender;
private StreamReader SrReciever;
private Thread thrMessaging;
private delegate void UpdateLogCallBack(string strMessage);
public MainWindow()
{
InitializeComponent();
}
private void btn_Connect_Click(object sender, RoutedEventArgs e)
{
TcpClient tcp = new TcpClient();
txt_Log.AppendText("connecting");
tcp.Connect(IPAddress.Parse("192.168.137.1"), 2000);
txt_Log.AppendText("Connected");
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void ReceiveMessages()
{
SrReciever = new StreamReader(tcp.GetStream());
while (true)
{
string response = SrReciever.ReadLine();
txt_Log.Dispatcher.Invoke(new UpdateLogCallBack(this.UpdateLog), new object[] { response });
}
}
private void UpdateLog(string strMessage)
{
txt_Log.AppendText(strMessage);
}
}
}
Running this gives me an error in the Receive messages method. It says the error is on the line with "SrReciever = new StreamReader(tcp.GetStream());" saying it a NullReferenceException, Object reference not set to an instance of an object.
I'm not the best at programming, so if there is an example out there for a TCP client that works in WPF then that will be very helpful.
Thanks
Nick
That is simply because you're creating a scoped variable here:
private void btn_Connect_Click(object sender, RoutedEventArgs e)
{
//TcpClient tcp = new TcpClient();
//this initialized a new tcp variable only here...
//do this instead...
tcp = new TcpClient();
//this will assign a new TcpClient to MainWindow.tcp
So what happens is MainWindow.tcp is actually null and then when ReceiveMessages is called you are trying to call GetStream a null value.
I have a refresh button to update news in my WP7 application. When I double or triple click on the refresh button I am getting an error
"WebClient does not support concurrent I/O operations" .
I think thats because It is sending the request triple times and making it crash. Here is my Click code.
private void NewsRefresh_Click(object sender, RoutedEventArgs e)
{
var vm = this.DataContext as MainPageViewModel;
if (vm != null)
{
vm.UpdateNews();
}
}
How can I turn it as "if It is busy cancel the process".
WebClient isn't very flexible but if you really want to use it you can make use of the IsBusy property and then cancel ongoing operation. Then, once it's cancelled you can restart it. There is important problem with synchronization. The operation which consists of checking IsBusy and invoking CancelAsync isn't atomic. Luckily DownloadStringCompleted is dispatched to the UI thread so you don't need to bother about synchronization. The snippet below shows how can you achieve it. For simplicity it's Windows Forms.
public partial class Form1 : Form
{
WebClient _WebClient;
bool _UpdateNews;
public Form1()
{
InitializeComponent();
_WebClient = new WebClient();
_WebClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(_WebClient_DownloadStringCompleted);
_UpdateNews = false;
}
void _WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (_UpdateNews)
{
_UpdateNews = false;
UpdateNews();
}
else if (e.Error != null)
{
// Report error
}
else
{
MessageBox.Show(e.Result);
}
}
private void button1_Click(object sender, EventArgs e)
{
if (_WebClient.IsBusy)
{
_WebClient.CancelAsync();
_UpdateNews = true;
}
else
{
UpdateNews();
}
}
private void UpdateNews()
{
_WebClient.DownloadStringAsync(new Uri("http://stackoverflow.com/questions/7084948/c-concurrent-i-o-operations-exception"));
}
}
The 'easy' way (though not bullet proof):
private void NewsRefresh_Click(object sender, RoutedEventArgs e)
{
try
{
NewsRefresh.Enabled = false;
var vm = this.DataContext as MainPageViewModel;
if (vm != null)
{
vm.UpdateNews();
}
}
finally
{
NewsRefresh.Enabled = true;
}
}
The more difficult approach would require more details on what exactly a MainPageViewModel is, and what UpdateNews() does. Basically you need to store a state value wherever you are storing the WebClient instance. Before using the WebClient you need check to see if you are already using it. The issue comes when multiple threads may operate on a single instance, or if you multiple operations (other than UpdateNews). When multiple threads are involved the easiest thing is to surround the usage of the WebClient with a Mutex.
Of course the other option is to not reuse the WebClient instance, rather create a new one for each new request.
UPDATE
Well, well, using DownloadStringAsync is certainly going to make things fun. The above code Disabling the UI will not work unless you move the re-enabling code. It would be easiest to go with my last suggestion and just create a new instance of WebClient. I'm not real fond of WebClient myself and prefer using WebRequest.Create.