I'm working on a Chat Application on Windows Form using C# Socket Programming.
Currently, my App send messages as "ME" and receives messages as "FRIEND".
What I want is to add a textbox which asks Client for username and server receives messages as that username. Following is my code:
namespace ServerClientChat
{
public partial class Form1 : Form
{
private TcpClient client;
public StreamReader STR;
public StreamWriter STW;
public string receive;
public string receive2;
public String text_to_send;
public Form1()
{
InitializeComponent();
IPAddress[] localIP = Dns.GetHostAddresses(Dns.GetHostName()); //getting own IP
foreach (IPAddress address in localIP)
{
if (address.AddressFamily == AddressFamily.InterNetwork)
{
textBox3.Text = address.ToString();
}
}
// textBox1.KeyDown += new KeyEventHandler(textBox1_KeyDown);
}
private void button3_Click(object sender, EventArgs e) //Connect to server
{
client = new TcpClient();
//set client side endpoint consisting of client's ip address and port
IPEndPoint IP_End = new IPEndPoint(IPAddress.Parse(textBox5.Text),int.Parse(textBox6.Text));
try
{
client.Connect(IP_End);
if(client.Connected)
{
textBox2.AppendText(">> Connected to Server"+ "\n");
STW = new StreamWriter(client.GetStream());
STR = new StreamReader(client.GetStream());
STW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync(); //start receiving data in background (async means non-blocked communication
backgroundWorker2.WorkerSupportsCancellation = true; //ability to cancel this thread
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
private void button2_Click(object sender, EventArgs e) //Start server
{
TcpListener listener = new TcpListener(IPAddress.Any,int.Parse(textBox4.Text)); //Listens for connections from TCP network clients.
listener.Start();
client = listener.AcceptTcpClient();
STR = new StreamReader(client.GetStream()); //Implements a TextReader that reads characters from a byte stream in a particular encoding.
STW = new StreamWriter(client.GetStream());
STW.AutoFlush = true; //Setting AutoFlush to true means that data will be flushed from the buffer to the stream after each write operation, but the encoder state will not be flushed.
backgroundWorker1.RunWorkerAsync(); //start receiving data in background (async means non-blocked communication
backgroundWorker2.WorkerSupportsCancellation = true; //ability to cancel this thread
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) //to receive data
{
while(client.Connected)
{
try
{
receive = STR.ReadLine();
this.textBox2.Invoke(new MethodInvoker(delegate () { textBox2.AppendText("Friend: " + receive + "\n"); }));
receive = "";
}
catch(Exception x)
{
MessageBox.Show(x.Message.ToString());
}
}
}
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) //to send data
{
if(client.Connected)
{
STW.WriteLine(text_to_send);
this.textBox2.Invoke(new MethodInvoker(delegate () { textBox2.AppendText("Me: " + text_to_send + "\n"); }));
}
else
{
MessageBox.Show("Send Failed");
}
backgroundWorker2.CancelAsync();
}
private void button1_Click(object sender, EventArgs e) //Send button
{
if(textBox1.Text!="")
{
text_to_send = textBox1.Text;
backgroundWorker2.RunWorkerAsync();
}
textBox1.Text = "";
}
private void Form1_Load(object sender, EventArgs e)
{
DialogResult f = MessageBox.Show("Welcome to My Chat App! Do you want to start your own Server? ", "Welcome!", MessageBoxButtons.YesNoCancel);
if (f == DialogResult.Yes)
{
button3.Enabled = false;
textBox5.Enabled = false;
textBox6.Enabled = false;
}
if (f == DialogResult.No)
{
button2.Enabled = false;
textBox3.Enabled = false;
textBox4.Enabled = false;
}
}
private void label5_Click(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
button1_Click(this, new EventArgs());
}
}
}
}
You can create something like your own protocol and send it to a server.
<username>YourName</username>
<msg>Hello World</msg>
But in real-life applications you should use database with user authorization process.
Related
Okay so I'm trying to do a two-way communication from C# to Arduino (using FTDI232) and viceversa, from Arduino to C#.
Here's the code:
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
private string inData;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("A");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("B");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
inData = myPort.ReadLine();
this.Invoke(new EventHandler(displayData_event));
}
private void displayData_event(object sender, EventArgs e)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + inData;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I have three problems. One is when I want to close the application, I want the Serial Communication to turn off, because I made it automatically open using Form1_Load, as soon as you start the debug, it also opens Serial Communication, and it remains on, but I don't want to use a button that I have to click first to close the application. I need to close Serial Communication automatically after I close the application.
The second problem is with the Serial Port that denies the communication, what I mean is that I need to switch from Receiving Data to Sending Data. Here's a picture of what it looks like: Application Image
The the third problem is the LED one. Well its similar to the second one, but this time when I click the button OFF, I want it to switch back to Receiving Data. Here's the picture:
Application Image 2
EDIT : This code is only temporary. I needed it to turn off the Serial Communication
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
You are initializing and opening the port many times. This is not allowed. Use a single initialization and keep the member. This makes the code much smoother, too.
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
try
{
myPort.WriteLine("A");
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
try
{
myPort.WriteLine("B");
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var inData = myPort.ReadLine(); // Use local variable
Invoke(new Action<string>(displayData_event), inData);
}
private void displayData_event(string data)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + data;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
myPort = null;
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I think I also fixed your event handling. One handler that gets the data and then forwards the received text is enough. You would also not really require the exception handling around WriteLine now, since that cannot really fail.
I'm coding a chat application with C# Windows Froms. My problem is that, my server can send messages to each connected client but only a client that sent a message can receive a response. I tried to create a function like ReceiveLoop() with an infinite loop inside or add a timer and call Receive() function for each tick but both were unsuccessful due to the app's crash.
How to get the data in real time? I attach my client's app code.
public partial class Form1 : Form
{
private string name;
private Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void Namebt_Click(object sender, EventArgs e)
{
if (!Test(Nametb.Text)) Nametb.Text = "Nie wpisano nazwy!";
else
{
name = Nametb.Text;
Nametb.Clear();
Nametb.Enabled = false;
Namebt.Enabled = false;
Messageslb.Enabled = true;
timer1.Start();
LoopConnect();
}
}
private void LoopConnect()
{
int attempts = 0;
while (!_clientSocket.Connected)
{
try
{
attempts++;
_clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Messageslb.Items.Clear();
Messageslb.Items.Add("Connection attempts: " + attempts.ToString());
Messageslb.Refresh();
}
}
Messageslb.Items.Add("Connected!");
Messageslb.Refresh();
Messagetb.Enabled = true;
Sendbt.Enabled = true;
}
private bool Test(string text)
{
if (text != "") return true;
return false;
}
private void Sendbt_Click(object sender, EventArgs e)
{
if (!Test(Messagetb.Text)) Messagetb.Text = "Nie wpisano zadnej wiadomosci!";
else
{
Send();
}
}
private void Receive()
{
if(_clientSocket.ReceiveBufferSize > 0)
{
byte[] receivedBuffer = new byte[1024];
int rec = _clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
Messageslb.Items.Add(Encoding.ASCII.GetString(data));
}
}
private void Send()
{
string message = "[" + name + "]: " + Messagetb.Text;
Messagetb.Clear();
byte[] buffer = Encoding.ASCII.GetBytes(message);
_clientSocket.Send(buffer);
Receive();
}
private void Nametb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) Namebt_Click(sender, e);
}
private void Messagetb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return) Sendbt_Click(sender, e);
}
private void timer1_Tick(object sender, EventArgs e)
{
Receive();
}
}
You need to run the receive method on a separate task.
_clientSocket.Receive(receivedBuffer);
should be:
private Task _receiving;
private void Receive()
{
if(_clientSocket.ReceiveBufferSize > 0)
{
if(_receiving == null || _receiving.IsCompleted)
_receiving = Task.Run(() =>
{
byte[] receivedBuffer = new byte[1024];
int rec = _clientSocket.Receive(receivedBuffer);
byte[] data = new byte[rec];
Array.Copy(receivedBuffer, data, rec);
Messageslb.Items.Add(Encoding.ASCII.GetString(data));
});
}
}
Otherwise clientSocket.Receive will hang your program.
You will want to make sure Messageslb is thread safe though, that will take further research.
If you're looking for real time communication look into RTC Client for C# https://msdn.microsoft.com/en-us/library/ms946701.aspx. Otherwise I would highly recommend Socket.IO since it is truly simple to use and set up with extremely fast rtc! https://socket.io/get-started/chat
I want to develop a client-server application. I started the project but I encountered the some problems. When I want to connect to server with one client, everything is done. Program is working. But when I want to connect with two or three etc. PC to server, clients of them is working but others is not working. How can I fix this problem?
Here is the my code;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Timers;
using ClientServer;
namespace ClientServer
{
public partial class Form1 : Form
{
private TcpClient Client;
private StreamReader STR;
public StreamWriter STW;
public string receive;
public string text_to_send;
//int zaman;
public Form1()
{
InitializeComponent();
- Client = new TcpClient();
Control.CheckForIllegalCrossThreadCalls = false; //cross threading problem
IPAddress[] LocalIP = Dns.GetHostAddresses(Dns.GetHostName()); // my IP Adress
foreach (IPAddress adress in LocalIP)
{
if(adress.AddressFamily== AddressFamily.InterNetwork)
{
textBox3.Text = adress.ToString();
}
}
}
private void button2_Click(object sender, EventArgs e) //Start server
{
TcpListener listener = new TcpListener(IPAddress.Any, int.Parse(textBox4.Text));
listener.Start();
Client = listener.AcceptTcpClient();
STR = new StreamReader(Client.GetStream());
STW = new StreamWriter(Client.GetStream());
STW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync(); //receive data background
backgroundWorker2.WorkerSupportsCancellation = true; //ability cancel this thread
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) //receive data
{
while(Client.Connected)
{
try
{
receive = STR.ReadLine();
if(receive=="soru1")
{
label7.Text = "Merhaba bu bir denemedir :)";
//zaman = 45;
timer1.Enabled = true;
}
this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("Sen:" + receive + "\n"); }));
receive = "";
}
catch(Exception x)
{
MessageBox.Show(x.Message.ToString());
}
}
}
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) //veri gönder
{
if(Client.Connected)
{
STW.WriteLine(text_to_send);
this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("Ben:" + text_to_send + "\n"); }));
}
else
{
MessageBox.Show("Gönderim başarısız!");
}
backgroundWorker2.CancelAsync();
}
private void button3_Click(object sender, EventArgs e) //Connect Server
{
Client = new TcpClient();
IPEndPoint IP_End = new IPEndPoint(IPAddress.Parse(textBox5.Text), int.Parse(textBox6.Text));
try
{
Client.Connect(IP_End);
if(Client.Connected)
{
textBox2.AppendText("Server'a bağlantı sağlandı" + "\n");
STW = new StreamWriter(Client.GetStream());
STR = new StreamReader(Client.GetStream());
STW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync(); //receive data in background
backgroundWorker2.WorkerSupportsCancellation = true; //
}
}
catch(Exception x)
{
MessageBox.Show(x.Message.ToString());
}
}
private void button1_Click(object sender, EventArgs e) //Send Button
{
if(textBox1.Text != "")
{
text_to_send = textBox1.Text;
backgroundWorker2.RunWorkerAsync();
}
textBox1.Text = "";
}
//private void timer1_Tick(object sender, System.EventArgs e) //
//{
// zaman--; //timer her saniyede sayıyı 1 azaltacak
// label9.Text = zaman.ToString();
// if (zaman == 0)
// {
// timer1.Enabled = false;
// }
//}
}
}
Here a good links:
http://www.mikeadev.net/2012/07/multi-threaded-tcp-server-in-csharp/
https://www.codeproject.com/Articles/511814/Multi-client-per-one-server-socket-programming-in
tcpListener.Start();
Console.WriteLine("************This is Server program************");
Console.WriteLine("Hoe many clients are going to connect to this server?:");
int numberOfClientsYouNeedToConnect =int.Parse( Console.ReadLine());
for (int i = 0; i < numberOfClientsYouNeedToConnect; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
There is a server and multiple clients. The server accepts the connection requests from multiple clients. The sockets created are stored in an array. There is a list box in my application. On selecting a particular item it refers to the corresponding socket in the array of sockets (eg if I select first item, it will consider first socket in the array). But the problem is - as the clients can connect to the server in random fashion how the server keep tracks of the clients if it has to send data to a particular client.
Here is my code:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
int i=0;
TcpListener listener = new TcpListener(8888);
listener.Start();
while(true)
{
Socket soc = listener.AcceptSocket();
socarray[i] = soc;
i++;
if (i == NUMBEROFCLIENTS)
break;
}
// Thread writetodatabase = new Thread(datawrite);
// writetodatabase.Start();
Application.Run(new Form1());
}
private void button5_Click(object sender, EventArgs e)
{
if (listBox1.Text == "Reader1")
{
reader_flag = 1;
toolStripStatusLabel1.Text = "reader1 selected";
a = toolStripStatusLabel1.Text;
}
if (listBox1.Text == "Reader2")
{
reader_flag = 2;
toolStripStatusLabel1.Text = "reader2 selected";
a = toolStripStatusLabel1.Text;
}
}
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string a;
public static int reader_flag = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
Form3 formmm = new Form3();
formmm.Show();
}
private void button4_Click(object sender, EventArgs e)
{
Form2 formm = new Form2();
formm.Show();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
byte[] bytesFrom = new Byte[1000];
Program.socarray[0].Receive(bytesFrom);
char[] stuffed = System.Text.Encoding.UTF8.GetString(bytesFrom).ToCharArray();
int i;
char escape='#';
List<char> unstuffed = new List<char>();
for(i=0;i<stuffed.Length;i++)
{
if(stuffed[i]==escape)
{
i++;
unstuffed.Add(stuffed[i]);
}
else
{
unstuffed.Add(stuffed[i]);
}
}
unstuffed.RemoveAt(0);
unstuffed.RemoveAt(unstuffed.Count-1);
char[] final;
final = unstuffed.ToArray();
string foo = new string(final);
textBox1.Text = foo;
System.IO.File.WriteAllText(#"C:\Users\cdac\Desktop\server\server\TextFile2.txt", foo);
}
finally { }
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
Form4 mm = new Form4();
mm.Show();
}
private void toolStripStatusLabel1_Click(object sender, EventArgs e)
{
toolStripStatusLabel1.Text = a;
}
private void button5_Click(object sender, EventArgs e)
{
if (listBox1.Text == "Reader1")
{
reader_flag = 1;
toolStripStatusLabel1.Text = "reader1 selected";
a = toolStripStatusLabel1.Text;
}
if (listBox1.Text == "Reader2")
{
reader_flag = 2;
toolStripStatusLabel1.Text = "reader2 selected";
a = toolStripStatusLabel1.Text;
}
}
private void button6_Click(object sender, EventArgs e)
{
string MyConString = "server=localhost;" +
"database=cdac;"+
"User Id=root;"
+"password=cdac56;";
MySqlConnection connection = new MySqlConnection(MyConString);
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
connection.Open();
//StreamReader reader = new StreamReader("C:\\tag_log_030610.txt");
StreamReader reader = new StreamReader("C:\\Users\\cdac\\Desktop\\server\\server\\TextFile2.txt");
string line;
while ((line = reader.ReadLine()) != null)
{
string[] parts = line.Split(';');
//command.CommandText = "insert into st_attn(rollno,Th_attn,Name) values('" + parts[0] + "','" + parts[1] + "','" + parts[2] + "')";
command.CommandText = "insert into st_attn(rollno) values('" + parts[0] + "')";
Reader = command.ExecuteReader();
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
Client-Server apps ALWAYS start with a request from the client to the server. No matter if it's a business app, a game, a website, a webservice or even something to tell the time, the client will always first ask the server.
This means that if you're using sockets, you will always have to let the request come from the client. He will send a request to the server. The server will then keep a record internally of where they can find the client. This is kept in the Endpoint property of the Socket. But normally, you will not have to worry about this unless you're working with push apps.
I have a system that makes a loop on all serial ports and send a command 'at' for them.
These ports return 'ok' in Putty, but in the C# the MessageBox is empty.
Why is this happening?
Putty: http://i.imgur.com/AZY7aRY.png /
C#: http://i.imgur.com/wgGyT2x.png
public partial class Form1 : Form
{
List<SerialPort> serialPort = new List<SerialPort>();
private delegate void SetTextDeleg(string text);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var portNames = SerialPort.GetPortNames();
foreach (var port in portNames)
{
SerialPort sp;
sp = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.None;
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.ReadTimeout = 500;
sp.WriteTimeout = 500;
serialPort.Add(sp);
listPorts.Items.Add(port);
}
}
private void listPorts_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
foreach (var sp in serialPort)
{
// Open port
try
{
if (!sp.IsOpen)
sp.Open();
sp.Write("at\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Error opening/writing to serial port :: " + ex.Message, "Error!");
}
}
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
SerialPort sp = (SerialPort)sender;
string data = sp.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
private void si_DataReceived(string data)
{
String retorno = data.Trim();
MessageBox.Show(data);
}
}
Your modem response something like this: \n\rOK\n\r you should read all stream in the buffer or you should read 3 time the serial port buffer with ReadLine() method.