Okay so I have ran into a problem, I have created a server which handles a single client and now I want to kick it up a notch and have it handle multiple clients at one time.
I have looked and tried to do this using HashTables and also Async but I keep getting stuck, this is a grey area for me as I have only just recently started dealing with sockets etc...
I wondered if anyone had a way of doing it?
Any advise will be taken on board.
This is my server code(If it helps).
namespace ChatServer
{
delegate void UpdateTextBox(string msg);
public partial class Form1 : Form
{
private TcpListener ConnectionListener;
private BinaryReader MessageReader;
private BinaryWriter MessageWriter;
private Socket ClientConnection;
private NetworkStream DataStream;
private Thread ListeningThread;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
try
{
IPAddress.Parse(textBox3.Text);//
ListeningThread = new Thread(new ThreadStart(ListenForConnections));
ListeningThread.Start();
}
catch (Exception)
{
MessageBox.Show("Wrong Ip Address");
}
}
private void button2_Click(object sender, EventArgs e)
{
try
{
if (ClientConnection.Connected)
{
MessageWriter.Write(textBox2.Text);
textBox2.Clear();
}
}
catch (Exception)
{
MessageBox.Show("no client is connected");
}
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
try
{
if (ClientConnection.Connected)
{
MessageWriter.Write(textBox2.Text);
textBox2.Clear();
}
}
catch (Exception)
{
MessageBox.Show("no client is connected");
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
private void ListenForConnections()
{
try
{
ConnectionListener = new TcpListener(IPAddress.Parse(textBox3.Text), 80);
ConnectionListener.Start();
ChangeTextBoxContent("Listening For Connections");
ClientConnection = ConnectionListener.AcceptSocket();
DataStream = new NetworkStream(ClientConnection);
MessageReader = new BinaryReader(DataStream);
MessageWriter = new BinaryWriter(DataStream);
ChangeTextBoxContent("Connection Received");
HandleConnection();
MessageReader.Close();
MessageWriter.Close();
DataStream.Close();
ClientConnection.Close();
}
catch (Exception)
{
MessageBox.Show("Unable to connect, wrong ip address");
}
}
private void HandleConnection()
{
string message;
do
{
try
{
message = MessageReader.ReadString();
ChangeTextBoxContent(message);
}
catch (Exception)
{
ChangeTextBoxContent("connection Lost");
break;
}
} while (true);
}
private void ChangeTextBoxContent(string tx)
{
if (textBox1.InvokeRequired)
{
Invoke(new UpdateTextBox(ChangeTextBoxContent), new object[] { tx });
}
else
{
textBox1.Text += tx + "\r\n";
}
}
}
}
Thank you in advance.
You should handle each of your connections in a separate thread. Create a loop that constantly listens for remote connections, and when a remote connection is called, create a new thread with the connection as the object parameter.
Related
When i scrolled this trackbar right or left, The value should has changed from zero to its max. value (255) and the LED at the output should has been brighter over trackbar values while scrolling right.
But this trackbar works like switch. Before trackbar is 127 the led is off and after that, led suddenly turns on.
Where do you think problem is?
c# code
{
public partial class Form1 : Form
{
SerialPort serialport;
public Form1()
{
InitializeComponent();
serialport = new SerialPort();
serialport.BaudRate = 9600;
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = "COM3";
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
try
{
serialport.PortName = textBox1.Text;
if (!serialport.IsOpen)
serialport.Open();
MessageBox.Show("connected");
}
catch
{
MessageBox.Show("error!");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
string ledval = trackBar1.Value.ToString();
textBox2.Text = ledval;
serialport.WriteLine(ledval);
serialport.WriteLine(",");
}
catch (Exception ex) { }
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Stop();
serialport.Close();
}
}}
arduino code
int led = 13;
String x;
int val;
void setup(){
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop(){
if(Serial.available()>0)
{
x=Serial.readStringUntil(',');
val=x.toInt();
analogWrite(led, val);
}
}
I am having some timing issues with the following code. Basically I have "recordingOn", when True, it's suppose to start writing frames to file. In the below program, when I sometimes do Stop_Button_Click, I get an exception on "writer1.Write(frame1);" line, this is likely because it's doing so after I've already done dispose(). How do I synchronize this? thanks!
private bool recordingOn = false;
private void ConnectCameras_Button_Click(object sender, EventArgs e)
{
if (!captureInProgress) //Start cameras streaming
{
camera1Capture.ImageGrabbed += ProcessFrame;
camera1Capture.Start();
}
else //Stop cameras streaming
{
camera1Capture.Stop();
imageBox1.Image = null;
camera1Capture.ImageGrabbed -= ProcessFrame;
}
captureInProgress = !captureInProgress;
}
private void ProcessFrame(object sender, EventArgs arg)
{
camera1Capture.Retrieve(frame1);
imageBox1.Image = frame1;
if (recordingOn)
{
try
{
writer1.Write(frame1);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private void Stop_Button_Click(object sender, EventArgs e)
{
// Doing other stuff...
recordingOn = false;
writer1.Dispose();
}
The basic issue is of shared variable across multiple threads. Please use lock to control access to shared variable. Lock ensures that at one time only one thread can access a variable.
private bool recordingOn = false;
private static object _lock = new Object();
private void ConnectCameras_Button_Click(object sender, EventArgs e)
{
if (!captureInProgress) //Start cameras streaming
{
camera1Capture.ImageGrabbed += ProcessFrame;
camera1Capture.Start();
}
else //Stop cameras streaming
{
camera1Capture.Stop();
imageBox1.Image = null;
camera1Capture.ImageGrabbed -= ProcessFrame;
}
captureInProgress = !captureInProgress;
}
private void ProcessFrame(object sender, EventArgs arg)
{
camera1Capture.Retrieve(frame1);
imageBox1.Image = frame1;
lock (_lock)
{
if (recordingOn)
{
try
{
writer1.Write(frame1);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
private void Stop_Button_Click(object sender, EventArgs e)
{
// Doing other stuff...
lock (_lock)
{
recordingOn = false;
writer1.Dispose();
}
}
Im trying to use the progress bar to track my download, the only problem the progress value changes only after the file is downloaded to the computer and not during its download.
Here is my code, any help will be appreciated.
public void DownloadZaq()
{
using (WebClient zaq = new WebClient())
{
zaq.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Zaq_DownloadProgressChanged);
zaq.DownloadFileCompleted += new AsyncCompletedEventHandler(Zaq_DownloadFileCompleted);
zaq.DownloadFileAsync(new Uri(http://example.com), #"c:\to\111.jpg");
}
}
public void Zaq_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("download completed");
}
public void Zaq_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
I think that DownloadFileAsync is blocking the main thread somehow while checking the DNS. This is what I would try
WebClient zaq;
public void DownloadZaq()
{
zaq = new WebClient();
zaq.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Zaq_DownloadProgressChanged);
zaq.DownloadFileCompleted += new AsyncCompletedEventHandler(Zaq_DownloadFileCompleted);
System.Threading.Tasks.Task.Run(() => // Workaround to allow Async call
{
try
{
zaq.DownloadFileAsync(new Uri(http://example.com), #"c:\to\111.jpg");
}
catch (Exception ex)
{
zag.Dispose();
}
});
}
public void Zaq_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("download completed");
zag.Dispose();
}
public void Zaq_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
I am trying to use sockets to send messages to computers, but I keep getting this error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
sw was null.
This is my code:
public partial class ServerGUI : Form
{
Socket soc;
StreamReader sr;
StreamWriter sw;
Stream s;
public ServerGUI()
{
InitializeComponent();
try
{
if (Server.port == 0)
{ }
else
{
textBox2.Text = Server.port.ToString();
}
}
catch (Exception) { }
}
private void button1_Click(object sender, EventArgs e)
{
connect();
}
void connect()
{
Server.port = int.Parse(textBox2.Text);
TcpListener listener = new TcpListener(IPAddress.Any, Server.port);
listener.Start();
soc = listener.AcceptSocket();
s = new NetworkStream(soc);
sr = new StreamReader(s);
sw = new StreamWriter(s);
sw.AutoFlush = true; // enable automatic flushing
if (soc.Connected == true)
{
Console.WriteLine("Connected");
sw.WriteLine("Server Connected");
}
this.Hide();
Menu menu = new Menu();
menu.Show();
}
void recieve()
{
Console.WriteLine(sr.ReadLine());
}
public void close()
{
s.Close();
soc.Disconnect(true);
Menu menu = new Menu();
menu.Close();
this.Show();
}
public void send(string msg)
{
sw.WriteLine(msg);
}
This is the code for the button:
ServerGUI sgui = new ServerGUI();
public Menu()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
sgui.close();
}
private void button2_Click(object sender, EventArgs e)
{
sgui.send(textBox1.Text);
}
The writeline code in the connect method works but the code in the send method doesn't. I have tried this question: What is a NullPointerException, and how do I fix it? but it has not helped me.
Thanks
If the send method is called before the connect method the the StreamWriter sw is set to null and a NullReferenceException is thrown inside the send method.
A quick fix is to check the sw property before using it like:
public void send(string msg)
{
if (sw != null)
sw.WriteLine(msg);
}
or with a newer C# language feature a little bit shorter:
public void send(string msg)
{
sw?.WriteLine(msg);
}
EDIT:
The problem is that with the line ServerGUI sgui = new ServerGUI(); you create a new (second) ServerGUI form after hiding the former one that hat its own sw property. This sw property has been never initialized because the created StreamWriter instance is part of the first gui that you just have hidden.
Although this design (strong coupling of forms without a data/service layer) is not ideal, a way to fix this is to pass the form instance to the Menu. E.g.
var menu = new Menu();
menu.ServerGui = this;
menu.Show();
and of course the Menu class has to introduce a ServerGUI property like public
class Menu {
...
public ServerGUI ServerGui {get; set;}
private void button1_Click(object sender, EventArgs e)
{
ServerGui.close();
}
private void button2_Click(object sender, EventArgs e)
{
ServerGui.send(textBox1.Text);
}
I have a C# form application that communicate with PLC via Kepware OPC Server.
But this communication slowdown my GUI. I use thread for communication but form tabpages still very slow. I am sending a part of my code. Where am I wrong?
public Form1()
{
InitializeComponent();
Connect_Opc_Server("Kepware.KEPServerEX.V5");
ConnectToSqlToRead();
ShowPartType(1);
}
private void timer_Kepware_Tick(object sender, EventArgs e)
{
Thread KepwareThread = new Thread(new ThreadStart(Kepware_Read_Write));
if (KepwareThread.IsAlive)
{ }
else
{
KepwareThread.Start();
}
}
public void Kepware_Read_Write()
{
if (KepwarePLCReadError == false)
{
synch_read();
}
if (KepwarePLCReadOK == true)
{
synch_write();
}
}
You might want to create only 1 thread.
private void timer_Kepware_Tick(object sender, EventArgs e)
{
if (_KepwareThread == null)
{
_KepwareThread = new Thread(...);
}
if (!_KepwareThread.IsAlive)
{
_KewpareThread.Start();
}
}