tcpClient and IRC client issues - c#

Can someone tell me why the following code isn't working?
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace TCPClient {
public partial class Form1 : Form {
private TcpClient client;
private Thread readThread;
private NetworkStream stream;
private Stream dataStream;
private Encoding dataStreamEncoding;
private StreamWriter writer;
private StreamReader reader;
public Form1() {
InitializeComponent();
this.client = new TcpClient();
this.readThread = new Thread(ReadLoop);
this.dataStreamEncoding = Encoding.Default;
Thread.CurrentThread.Name = "MainThread";
this.readThread.Name = "ReadThread";
}
private void btnConnect_Click(object sender, EventArgs e) {
if (this.client != null && !this.client.Connected) {
try {
this.client.Connect("open.ircnet.net", 6666);
if (this.client != null && this.client.Connected) {
Console.WriteLine("Connected");
}
// Set up network I/O objects.
this.stream = this.client.GetStream();
this.writer = new StreamWriter(this.stream, this.dataStreamEncoding);
this.reader = new StreamReader(this.stream, this.dataStreamEncoding);
//HandleClientConnected(state.Item3);
this.readThread.Start();
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
private void btnPing_Click(object sender, EventArgs e) {
Console.WriteLine("Ping Sent");
this.writer.Write("PING");
this.writer.Flush();
}
private void btnLogin_Click(object sender, EventArgs e) {
Console.WriteLine("Login Info Sent");
this.writer.Write( "PASS *\r\n" +
"NICK testing3134\r\n" +
"USER guest 8 * :\"John Doe\"");
this.writer.Flush();
}
private void ReadLoop() {
try {
// Read each message from network stream, one per line, until client is disconnected.
while (this.client != null && this.client.Connected) {
var line = this.reader.ReadLine();
if (line == null)
break;
Console.WriteLine(line);
}
if(!this.client.Connected) {
Console.WriteLine("Disconnected");
}
} catch(Exception ex) {
Console.WriteLine(ex.Message);
}
}
}
}
Console:
Connected
:ircnet.eversible.com 020 * :Please wait while we process your connection to ircnet.eversible.com
Login Info Sent
Ping Sent
The thread 'ReadThread' (0x10bc) has exited with code 0 (0x0).
ERROR :Closing Link: testing3134[unknown#24.255.34.216] (Ping timeout)
Changes that made it work:
Original:
private void btnPing_Click(object sender, EventArgs e) {
Console.WriteLine("Ping Sent");
this.writer.Write("PING");
this.writer.Flush();
}
private void btnLogin_Click(object sender, EventArgs e) {
Console.WriteLine("Login Info Sent");
this.writer.Write( "PASS *\r\n" +
"NICK testing3134\r\n" +
"USER guest 8 * :\"John Doe\"");
this.writer.Flush();
}
WORKING:
private void btnPing_Click(object sender, EventArgs e) {
Console.WriteLine("Ping Sent");
this.writer.WriteLine("PING\r\n");
this.writer.Flush();
}
private void btnLogin_Click(object sender, EventArgs e) {
Console.WriteLine("Login Info Sent");
this.writer.WriteLine("PASS *\r\n");
this.writer.Flush();
this.writer.WriteLine("NICK testing3134\r\n");
this.writer.Flush();
this.writer.WriteLine("USER guest 8 * :\"John Doe\"\r\n");
this.writer.Flush();
}
Not only did I switch from Write to WriteLine but like the accepted answer suggests I add line returns to the end of all the requests being sent.

You're not including a line break after the PING or USER messages.
From RFC 2812:
IRC messages are always lines of characters terminated with a CR-LF (Carriage Return - Line Feed) pair
So you should have:
this.writer.Write("PASS *\r\n" +
"NICK testing3134\r\n" +
"USER guest 8 * :\"John Doe\"\r\n");
and:
this.writer.Write("PING\r\n");
I'd also avoid using Encoding.Default if I were you. The RFC specifies that no particular character encoding is used, but it does expect it to be an 8-bit one (rather than potentially multi-byte). This is a poor way of specifying an encoding, but I'd probably use either ASCII or ISO-8859-1 explicitly.

SOmething else to consider here is that most irc servers send you a "ping cookie" when you connect. This consists of a PING message with a random string as its parameter. You MUST respond to this with a PONG containing the same random string, or your connection will be terminated with a "Ping Timeout" message. This is a simple method of preventing fire-and-forget use of irc through proxies, and is very common.
You should add functionality to work with this into your client.

Related

How to prevent "datas delays" in Serial Communication (C# form <-> Arduino)

The code i have works, but i want to make sure it's robust, as i remember writing similar code in the past (with python) and noticing that i was receiving datas that would be 3 or 4 minutes old and would get even older with time.
I guess this has to do with the serial buffer, and that i should "clear it" from time to time, what is the best practice for this ?
C# form code:
using System;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialTest1
{
public partial class Form1 : Form
{
public SerialPort ArduinoSerial;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Timer MyTimer = new Timer();
MyTimer.Interval = (1000); // 1 sec
MyTimer.Tick += new EventHandler(SerialTimer_Tick);
MyTimer.Start();
Console.WriteLine("Form1_Loading....");
OpenSerialPort();
}
private void OpenSerialPort() // creating serial communication object
{
try
{
Console.WriteLine("OpenSerialPort: opening port.....");
ArduinoSerial = new SerialPort("COM7", 115200);//Set board COM
ArduinoSerial.Open();
ArduinoSerial.DataReceived += new SerialDataReceivedEventHandler(dataReceived);
}
catch (Exception ex)
{
Console.WriteLine("OpenSerialPort: Can not find port");
}
}
// write to arduino and restart Serial com if error like cable disconnected and reconnected
private void writeToArduino()
{
try
{
Console.WriteLine($"writeToArduino: writing msg to arduino");
ArduinoSerial.WriteLine("hello from pc");
}
catch (Exception ex)
{
Console.WriteLine("writeToArduino: Serial Error");
//MessageBox.Show("Serial Error: " + ex.ToString(), "ERROR");
if (!ArduinoSerial.IsOpen)
{
Console.WriteLine("writeToArduino: ArduinoSerial is close, opening it...");
OpenSerialPort();
}
}
}
private void SerialTimer_Tick(object sender, EventArgs e) // will write to arduino at each timer tick
{
writeToArduino();
}
private void dataReceived(object sender, SerialDataReceivedEventArgs e) // receiving datas from arduino
{
string SerialLine = ArduinoSerial.ReadLine();
Console.WriteLine($"dataReceived: Got serial line for arduino: {SerialLine}");
}
}
}
Arduino code:
#include <TimeLib.h>
#include <Time.h>
//WINDOWS COMMUNICATION
String receivedString;
void setup(void) {
Serial.begin(115200);
}
void loop(void) {
static time_t lastMsg = 0;
static int counter = 1;
if (now() - lastMsg > 1) {
lastMsg = now();
Serial.print("msg ");
Serial.print(counter);
Serial.println("Hello from arduino");
counter++;
}
while (Serial.available() > 0) {
receivedString = Serial.readString();
Serial.println(receivedString);
}
delay(5);
}

UdpClient does not receive any data

So, This has me confused for a while. I can't think of a simpler program to write and test. I initialize the UdpClient and call Receive method on a separate thread.Here is the complete code:
UdpClient client = new UdpClient(1414);
byte[] data = new byte[320];
IPEndPoint localpt = new IPEndPoint(IPAddress.Any,0);
const string START_COMMAND = "START";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
client.Connect("192.168.1.12",33051);
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
while (client.Available > 0)
{
data=client.Receive(ref localpt);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void button1_Click(object sender, EventArgs e)
{
byte[] START_BYTES = Encoding.ASCII.GetBytes(START_COMMAND);
client.Send(START_BYTES, START_BYTES.Length);
}
After setting a breakpoint on while (client.Available > 0) I noticed that client.Available is always zero.
Things that I've tried:
1-Check if I'm able to ping the remote host(OK I am able to Ping)
2-Check if there is any data available on the network interface(OK Used wireshark and saw incoming packets)
3-Check if my application is allowed to go through firewall(OK Explicitly added my exe to go through windows firewall)
4-Disable(Uninstall) any firewall or antivirus programs(OK)
Yet I cannot receive any data from inside my app. Through further investigation I found out that it is possible to send data(The remote host receives my data) but I can never receive any.

Close application after reading upper code c#

I am working with arduino serial monitor. My goal is to connect through serial port, send some data and close the application after it's done.
This is a C# application. Everything works well besides the fact that the application does not close. To solve the issue, I added Application.Exit() call at the end of Form1_Load method. After this change, the application starts and closes without reading the uppercase letter that I'm sending.
Source code:
namespace ForTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
foreach (string port in ports)
{
SerialPort sp = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
try
{
sp.Open();
try
{
sp.WriteLine("Z"); // Send 1 to Arduino
sp.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
catch (Exception ek)
{
System.Diagnostics.Debug.WriteLine(ek.Message);
}
}
Application.Exit();
}
private void label2_Click(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
if I understood properly, you want to send data FROM C# to ARDUINO and then you exit the C# app
you can't just call Application.exit() after the InitializeComponent(), instead to achieve that you need to exit after sending the data
sp.WriteLine("Z"); // Send 1 to Arduino
sp.Close();
Application.Exit(); ///here!!

Capturing serial welcome message when connecting in c#

I am trying to write a program that communicates with a controller. The controller is supposed to send a "welcome" message when a connection is successfully established and, in fact, it does when I connect using a communications software. However, using the .NET code below, I never see the welcome message. Beyond that, it works. How can I capture this message. It seems to be sent the moment the connection is established.
Again, I am able to communicate fine with the controller after connection but I simply cannot seem to get the welcome message that is sent a the moment the connection is opened.
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
SerialPort sp;
public Form1()
{
InitializeComponent();
}
public void AddDataMethod(String myString)
{
richTextBox1.AppendText(myString);
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
sp = new SerialPort(comboBox1.SelectedItem.ToString(),Int32.Parse(comboBox2.SelectedItem.ToString()));
sp.DataReceived += SerialPort_OnDataReceived;
sp.Close();
sp.Open();
richTextBox1.AppendText("open\n");
button2.Enabled = true;
button3.Enabled = true;
}
catch (Exception ex)
{
richTextBox1.AppendText(ex.Message);
}
}
void SerialPort_OnDataReceived(object sender,SerialDataReceivedEventArgs args)
{
SerialPort sp = sender as SerialPort;
string s = sp.ReadExisting();
richTextBox1.Invoke(this.myDelegate, new Object[] { s });
}
private void button2_Click(object sender, EventArgs e)
{
sp.WriteLine(textBox1.Text);
textBox1.Text = "";
}
private void button3_Click(object sender, EventArgs e)
{
sp.DiscardOutBuffer();
sp.DiscardInBuffer();
sp.Close();
richTextBox1.AppendText("\nclosed\n");
}
private void Form1_Load_1(object sender, EventArgs e)
{
this.myDelegate = new AddDataDelegate(AddDataMethod);
string[] Ports = SerialPort.GetPortNames();
comboBox2.SelectedIndex = comboBox2.Items.Count - 1;
Array.Sort(Ports, (a, b) => string.Compare(a.Substring(3).PadLeft(3, '0'), b.Substring(3).PadLeft(3, '0')));
foreach (string port in Ports)
{
comboBox1.Items.Add(port);
}
comboBox1.SelectedIndex = 0;
}
}
}
I worked it out. Required a slight delay between connection and trying to pull data from the port.

Multi client chat in C# using form and TCP Protocol (not UDP)

I have tried 2 of how to make multi client, which is multi thread and asynchronous server. Both didn't work for me. The multi thread can make client send broadcast to all client, but some of them didn't receive the broadcasted data. While the asynchronous server cannot make the client connect too long. I don't know whether it's my code that's wrong or what. Please help me based on my latest working code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace Server
{
public partial class Form1 : Form
{
private TcpClient client;
public StreamReader STR;
public StreamWriter STW;
public string receive;
public String text_to_send;
public Form1()
{
InitializeComponent();
IPAddress[] localIP = Dns.GetHostAddresses(Dns.GetHostName()); //Using the PC's IP
foreach (IPAddress address in localIP) {
if (address.AddressFamily == AddressFamily.InterNetwork) {
textBox5.Text = address.ToString();
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e) //Button to start the server
{
TcpListener listener = new TcpListener(IPAddress.Any, int.Parse(textBox6.Text));
listener.Start();
client = listener.AcceptTcpClient();
STR = new StreamReader(client.GetStream());
STW = new StreamWriter(client.GetStream());
STW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync(); //Start receiving data in the background
backgroundWorker2.WorkerSupportsCancellation = true; //Cancel the active thread
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) //Receiving data
{
while(client.Connected)
{
try
{
receive = STR.ReadLine();
this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("You : " + receive + "\n Received : " + receive.Length.ToString() + " byte. \n"); }));
receive = "";
}
catch(Exception x)
{
MessageBox.Show(x.Message.ToString());
}
}
}
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) //Sending data
{
if (client.Connected)
{
STW.WriteLine(text_to_send);
this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("Me : " + text_to_send + "\n Sent : " + text_to_send.Length.ToString() + " byte \n"); }));//Text that will appeared on the screen after we enter the text that we type
}
else
{
MessageBox.Show("Send Failed!");
}
backgroundWorker2.CancelAsync();
}
private void button3_Click(object sender, EventArgs e) //Connected as client
{
client = new TcpClient();
IPEndPoint IP_End = new IPEndPoint(IPAddress.Parse(textBox3.Text), int.Parse(textBox4.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 the background
backgroundWorker2.WorkerSupportsCancellation = true; //Cancel the active thread
}
}
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 label1_Click(object sender, EventArgs e)
{
}
}
}
N.B : Just translated the comment into English

Categories

Resources