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.
Related
i am using Supersimpletcp C# library and TCP server code is here:
using SuperSimpleTcp;
void Main(string[] args)
{
// instantiate
SimpleTcpServer server = new SimpleTcpServer("127.0.0.1:9000");
// set events
server.Events.ClientConnected += ClientConnected;
server.Events.ClientDisconnected += ClientDisconnected;
server.Events.DataReceived += DataReceived;
// let's go!
server.Start();
// once a client has connected...
server.Send("[ClientIp:Port]", "Hello, world!");
Console.ReadKey();
}
static void ClientConnected(object sender, ConnectionEventArgs e)
{
Console.WriteLine($"[{e.IpPort}] client connected");
}
static void ClientDisconnected(object sender, ConnectionEventArgs e)
{
Console.WriteLine($"[{e.IpPort}] client disconnected: {e.Reason}");
}
static void DataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine($"[{e.IpPort}]: {Encoding.UTF8.GetString(e.Data.Array, 0, e.Data.Count)}");
}
On TCP Server implementation, I want to allow any client to have just one connection, if a previously connected client reconnects, previous connection must die, how can I provide it?
I researched on google and could not find any solution, documentation or tutorial for supersimpletcp.
If you guys have any suggestion, any kind of simple TCP library that provides good configuration oppurtunities etc., feel free to tell me.
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.
I'm trying to open a TCP/IP listener but when I run the code below, it crashes. It doesn't give me an error because when it crashes, it freezes and stops responding.
TcpListener server = new TcpListener(IPAddress.Any, 619);
TcpClient client;
private void button3_Click(object sender, EventArgs e)
{
server.Start();
client = server.AcceptTcpClient();
if (client.Connected)
{
MessageBox.Show("connected");
}
}
I know for a fact this port is free so that's not it. it crashes on this line:
client = server.acceptTcpClient();
You're executing a blocking call on the UI thread which gives the appearance of a "Crashing" application.
You need to use another thread or do things asynchronously. Background worker might be a starting point.
private BackgroundWorker bgw = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
bgw.DoWork += Bgw_DoWork;
bgw.RunWorkerCompleted += Bgw_RunWorkerCompleted;
bgw.WorkerSupportsCancellation = true;
}
private void button3_Click(object sender, EventArgs e)
{
if (!bgw.IsBusy)
{
bgw.RunWorkerAsync();
((Button)sender).Content = "Cancel";
}
else
{
bgw.CancelAsync();
}
}
private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button.Content = "Start";
}
private void Bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
var server = new TcpListener(IPAddress.Any, 619);
server.Start();
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
server.Stop();
break;
}
else
{
if (server.Pending())
{
var client = listener.AcceptTcpClient();
// handle client here or do something like below to return the client to the RunWorkerCompleted method in
// e.result
e.Result = client;
break;
}
}
}
}
There are other options such as using server.AcceptTcpClientAsync() instead of polling the server.Pending() property. Also, polling in this way without using Thread.Sleep in between may be overkill, i.e., you're checking the property very frequently and wasting cycles.
Following all of that, you need to figure out a way to deal with the client in a way that makes sense for your application. One click per client accepted? Handle new connections forever as they arrive until you cancel the listener? Etc. Good luck
BackgroundWorker tutorial
AcceptTcpClientAsync MSDN
This is expected behaviour. Your program hasn't crashed - the call to AccpetTcpClient() blocks waiting for an incoming connection:
https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.accepttcpclient(v=vs.110).aspx
You need to also open a TCP connection to port 619 from another thread, then your program will continue to run.
AcceptTcpClient is a blocking method
(https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.accepttcpclient%28v=vs.110%29.aspx).
When you call AcceptTcpClient, it will wait until a connection is made. Because it waits on the main thread (where also the GUI is running on), it will look like the program is frozen. Try using AcceptTcpClientAsync or putting the accepting part in a different thread. That should solve your problem.
Desirius
I'm creating a C# Socket Server, it already works, but now, when I press "Start" the "design" of the application doesn't load, it's not visible.
The socket server is running correcty (I see it working in the output window), I don't see any kind of error. I start deleting parts of the code, and the design stops being visible after this line:
TcpClient client = server.AcceptTcpClient();
...
If I remove from this line to the end, it appear again.
What's going on? (sorry for my bad english)
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
start();
}
private void start() {
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
server.Start();
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Client connected.");
}
I Think the problem is that the load is interrupted while the socket is working waiting for connections.
I'm trying to execute "start()" function on Form1_Shown but it does not work.
How can I be sure to start the socket server after the Form is full loaded?
server.AcceptTcpClient() is a blocking call and you are making it on the UI thread. You have a few options, here they are in the order I would do them.
Make the function you are calling it from async and use AcceptTcpClientAsync.
//Event handlers like `Load` are the only place you are allowed to do "async void"
private async void Form1_Load(object sender, EventArgs e)
{
await start();
}
private async Task start() {
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
server.Start();
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine("Client connected.");
}
If you can't use async/await because of the version of .NET you are targeting use BeginAcceptTcpClient to have a callback accept the client instead.
private void Form1_Load(object sender, EventArgs e)
{
start();
}
private void start() {
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
server.Start();
server.BeginAcceptTcpClient(AcceptClient, server);
}
private void AcceptClient(IAsyncResult result)
{
var server = (TcpListener)result.AsyncState;
TcpClient client = server.EndAcceptTcpClient(result);
Console.WriteLine("Client connected.");
}
Or one other option is put the code you currently have on a background thread via a Task.Run( or similar. However, I really would not recommend this approach, you tie up a thread just waiting for a new connection, the framework already provides better ways to do this without a thread by using async/await or the begin/end pair.
private void Form1_Load(object sender, EventArgs e)
{
Task.Run(() => start());
}
private void start() {
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
server.Start();
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Client connected.");
}
Hello friends have a form in C # that reads data from a serial device connected, my problem is that I even changing form of the method myPort.DataReceived still running and receiving data. There's no way I close the connection with the serial port because the method does not stop excutar. I've tried a command to zip it when I change my form but it crashes when you try to run the myPort.Close, I believe that is why the myPort.DataReceived still running, so I removed the code and it continues myPort.Close open in another form. I think my solution would be to stop the myPort.DataReceived to then close connection, but can not find way to do this.Below is an excerpt from my code:
namespace EntradaFinalCliente
{
public partial class ConsultaSerial : Form
{
string SerialString;
private SerialPort myport;
public ConsultaSerial()
{
InitializeComponent();
abrirSerial();
lerDados();
}
public void abrirSerial()
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = SerialPort1;
myport.DataReceived += myport_DataReceived;
}
private void lerDados()
{
if (myport.IsOpen == false)
{
try
{
myport.Open();
}
catch
{
return;
}
}
}
private void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
SerialString = myport.ReadExisting();
this.Invoke(new EventHandler(Analisa));
}
private void Analisa(object sender, EventArgs e)
{
checarSerial();
}
And this is my closing the form button:
private void button1_Click (object sender, EventArgs e)
{
myPort.Close ();
this.Hide ();
var form1 = new Form1 ();
form1.Closed + = (s, args) => this.Close ();
Form1.Show ();
}
The issue you have it that once the event has been triggered, your application would have entered the function myport_DataReceived. The function will continue to execute regardless of whether the port has been closed. If the port has been closed, the function would execute for the last time. Waiting for 100ms makes it worse. So my advice is to remove the wait and put a try catch statement around the code to make the thread terminate cleanly.
Furthermore, it is better if you use the sender to read the incoming data than using the member myPort because the sender is the one that fires the event. It also helps to remove confusion when you open two or more ports.
It is also advised that the body of DataReceived event handler function should be kept to minimum. Only do what you need to get the data out. You can then store the data in memory and do more complicated handling somewhere else using the stored data.
private void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100); // Why do you need to wait for 100 ms? If the event reaches here, it will have the data to read. Can remove?
try
{
SerialPort sp = (SerialPort)sender;
SerialString = sp.ReadExisting();
this.Invoke(new EventHandler(Analisa));
}
catch (Exception ex)
{
// Do something else
Console.WriteLine(ex.Message);
}
}