Determine if NamedPipeClientStream is connected - c#

I've problem with process communication using PipeConnection
My idea is:
A - process A
B - process B
1. A(pile client) wants to send message to B(pipe server)
2. B reads message and disconects.
2.1 If B needs to ansver
2.2 B(pipe client) connects to A(pile server)
2.3 A reads message and disconects.
The problem appears if A sends message to B and than imedlitley wants to send another message again
Code sample:
//Server
static void Main(string[] args)
{
using (NamedPipeServerStream server = new NamedPipeServerStream("EOG", PipeDirection.In))
{
StreamReader sr = new StreamReader(server);
while (true)
{
server.WaitForConnection();
Console.WriteLine("Conected to client");
try
{
Console.WriteLine(sr.ReadLine());
server.Disconnect();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
sr.Dispose();
}
}
}
//Client
static void Main(string[] args)
{
using (NamedPipeClientStream client = new NamedPipeClientStream(".", "EOG", PipeDirection.Out))
{
StreamWriter sw = new StreamWriter(client);
while (true)
{
Console.WriteLine("Message: ");
sw.WriteLine(Console.ReadLine());
if (!client.IsConnected)
client.Connect();
sw.Flush();
}
sw.Dispose();
}
Console.ReadKey();
}

Related

c# windows forms app /client server /checking client input to do something is not working in

I'm creating a client server app using c# and what it does :
1- the client sends a msg then the server sends it back to the client
2- I want to check what the client send and do some process like if the client send "chrome"
the server checks it and open chrome.exe
I don't know why its not working here on my code:
when the client sends chrome it always shows client disconnected message
also i cant convert it to windows froms app its shows lots of errors
#server code!
using System;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Net;
using System.Text;
namespace consoleTcpServer {
class Program {
class ConnectionHandler {
private Socket client;
private NetworkStream ns;
private StreamReader reader;
private StreamWriter writer;
private static int connections = 0;
//The constructor take the accepted client as argument
public ConnectionHandler(Socket client) {
this.client = client;
}
public void HandleConnection() {
try {
ns = new NetworkStream(client);
reader = new StreamReader(ns);
writer = new StreamWriter(ns);
connections++;
Console.WriteLine("New client accepted: {0} active connections",
connections);
writer.WriteLine("Welcome to my server");
writer.Flush();
string input;
while ((input = reader.ReadLine()).Length != 0) {
if (input.Contains("chrome")) {
System.Diagnostics.Process.Start("chrome.exe", "www.google.com");
} else if (input.Contains("fox")) {
System.Diagnostics.Process.Start("firefox.exe", "www.facebook.com");
}
Console.WriteLine(input);
writer.WriteLine(input);
writer.Flush();
}
// ns.Close();
// client.Close();
connections--;
Console.WriteLine("Client disconnected: {0} active connections", connections);
} catch (Exception) {
connections--;
Console.WriteLine("Client disconnected: {0} active connections",
connections);
}
}
}
static void Main(string[] args) {
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 9050);
server.Bind(localEP);
server.Listen(10);
Console.WriteLine("Waiting for a client");
while (true) {
try {
Socket client = server.Accept();
ConnectionHandler handler = new ConnectionHandler(client);
Thread thread = new Thread(new ThreadStart(handler.HandleConnection));
thread.Start();
} catch (Exception) {
Console.WriteLine("Connection failed ..");
}
//client.Close();
//server.Shutdown();
}
}
}
}
#client code
using System;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace consoleTcpClient {
class Program {
static void Main(string[] args) {
// Console.WriteLine("Hello World!");
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
client.Connect(remoteEP);
NetworkStream stream = new NetworkStream(client);
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
String input = reader.ReadLine();
Console.WriteLine(input);
String line = null;
while (true) {
Console.Write("Enter Message for Server <Enter to Stop >: ");
line = Console.ReadLine();
//writing for server
writer.WriteLine(line);
writer.Flush();
if (line.Length != 0) {
line = "Echo: " + reader.ReadLine();
Console.WriteLine(line);
}
}
// client.Close();
}
}
}

sr.ReadLine() isn't receiving data that is being sent

I am trying to implement an authentication method for my program. I have a server-side program that handles authentication:
class Program
{
static TcpListener listener = new TcpListener(9120);
public const string DECRYPT_KEY = "KObOBonONoinbOClHNKYJkgIKUFkjfKcvCYckcvBBCVKcbvHHCxthjcTJYBXJahjh";
static void Main(string[] args)
{
listener.Start();
while (true)
{
if (listener.Pending())
{
new Thread(TryAuthenticate).Start();
}
}
}
static void TryAuthenticate()
{
TcpClient needsAuth = listener.AcceptTcpClient();
StreamReader sr = new StreamReader(needsAuth.GetStream());
string line = sr.ReadLine();
if (!line.StartsWith("AUTH? ")) return;
StreamReader sr2 = new StreamReader("keys.pks");
string line2;
while ((line2 = sr2.ReadLine()) != null)
{
if (line == line2)
{
new StreamWriter(needsAuth.GetStream()).WriteLine("AFFIRMATIVE");
sr.Close();
}
}
sr2.Close();
needsAuth.Close();
}
}
And on the client-side I have this code:
class Authentication
{
public static bool Authenticate(string id)
{
if (id == "dEbUg2020") return true;
TcpClient client = new TcpClient("127.0.0.1", 9120);
StreamWriter sw = new StreamWriter(client.GetStream());
StreamReader sr = new StreamReader(client.GetStream());
sw.WriteLine("AUTH? " + id);
if (sr.ReadLine() == "AFFIRMATIVE")
{
sw.Close();
sr.Close();
client.Close();
return true;
}
else
{
sw.Close();
sr.Close();
client.Close();
return false;
}
}
}
I have tried debugging on both the client and the server side.
On the client-side, it starts hanging at if (sr.ReadLine() == "AFFIRMATIVE").
On the server-side, it starts hanging at string line = sr.ReadLine();.
I have done some research and it has told me that when sr.ReadLine() is expecting data but doesn't get any, it hangs until it does.
But I have sent data, and both the client/server hangs indefinitely until it crashes. I am stuck, does anyone know why this isn't working?
After writing a message with your sw StreamWriter, you need to flush it with sw.Flush(); for it to actually be sent to the other side.
So
sw.WriteLine("Some line");
sw.Flush();
Otherwise, you're not sending anything.

Named Pipe Input Output in C#

I am working with named pipes and very confused about how the interaction between the client and server is happening.
My server is a VM with a named pipe attached to it. I have created a client stream in C# this way:
NamedPipeClientStream client = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut);
Let's say the VM prompt is like below:
Hello!
Do you accept (y/n): y
Text1 : 1.2.3.4
Text2 : 2.3.4.5
What I essentially need to do is, check if the line read by the stream is "Do you accept (y/n):", if it matches then write y to the stream.es with Text1, then write 1.2.3.4 in the stream
Problems I am facing:
The prompt doesn't display anything after Hello!. What I thought
is, it is maybe waiting for the next input. So, instead of doing
this:
if(line.contains("Do you accept (y/n):"))
writer.writeLine("y")
I did this:
if(line.contains("Hello!"))
writer.writeLine("y");
Is this the correct thing? If it is, then it means that the server
isn't pushing the text in the buffer on which it is awaiting input.
So, every time I'll have to do the check for the previous line and
write the output of the next expected line to the writer stream?
Also, as per above, for passing 1.2.3.4 for Text1, I did this:
if(line.contains("Do you accept (y/n):"))
writer.writeLine("1.2.3.4")
What appears in my execution prompt is: Text1 : 1111111 ie. it's
only repeating the first character of the input I have passed. Why
such? I have already set AutoFlush = true to my writer stream.
Any pointers here will be highly appreciated!
Edit: Including the snippet
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Windows;
namespace App1 {
static void Main(string [] args) {
NamedPipeClientStream client = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut);
while(!client.IsConnected);
Streamreader reader = new StreamReader(client);
StreamWriter writer = new StreamWriter(client);
string line = "";
writer.AutoFlush = true;
while((line = reader.readLine()) != null) {
if(line.Contains("Hello!") {
writer.writeLine("1.2.3.4"); // input for the next prompt
}
else if(line.Contains("Text1") {
writer.writeLine("2.3.4.5"); // input for next prompt of Text2
}
writer.Flush();
writer.WaitForPipeDrain();
}
}
}
Is above the right way?
Also, sometimes the pipe reader is missing data. Like it shows Tet1 instead of Text1. Why such?
You have this statement: while(!client.IsConnected); which causes the client to wait for the connection before proceeding. However, the client never attempts to connect (client.Connect();), so presumably you will be waiting forever. Replace that line with if (!client.IsConnected) {client.Connect();} to get this to work.
Beyond that, per the comments, without knowing what your server side code looks like it's hard to say what the client should be sending; as the two sides are having a scripted conversation.
Here's an example of some working server & client code to illustrate how you could perform this conversation:
Code to kick off both client & server:
static void Main()
{
var server = Task.Factory.StartNew(() => RunServer());
var client = Task.Factory.StartNew(() => RunClient());
Task.WaitAll(server, client);
Console.WriteLine("Done");
}
Client code:
static void RunClient()
{
using (var pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut))
{
Console.WriteLine("Client is waiting to connect");
if(!pipeClient.IsConnected){pipeClient.Connect();}
Console.WriteLine("Client is connected");
using (var reader = new StreamReader(pipeClient))
{
using (var writer = new StreamWriter(pipeClient))
{
var running = true;
while(running)
{
Console.WriteLine("Client is waiting for input");
var message = reader.ReadLine();
if (message != null)
{
Console.WriteLine("Client: Recieved from server {0}", message);
switch (message)
{
case "Do you accept (y/n):":
writer.WriteLine("y");
writer.WriteLine("quit");
writer.Flush();
break;
case "quit":
running = false;
break;
}
}
}
}
}
}
Console.WriteLine("Client Quits");
}
Server code:
static void RunServer()
{
using (var pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut))
{
using (var reader = new StreamReader(pipeServer))
{
using (var writer = new StreamWriter(pipeServer))
{
var running = true;
Console.WriteLine("Server is waiting for a client");
pipeServer.WaitForConnection();
Console.WriteLine("Server has connection from client");
Console.WriteLine("Server: Saying Hi");
writer.WriteLine("Hello!");
Console.WriteLine("Server: Prompting for Input");
writer.WriteLine("Do you accept (y/n):");
writer.Flush();
while(running)
{
pipeServer.WaitForPipeDrain();
var message = reader.ReadLine();
Console.WriteLine("Server: Recieved from client {0}", message);
if (message.Equals("quit"))
{
writer.WriteLine("quit");
running = false;
}
}
}
}
}
Console.WriteLine("Server Quits");
}
Update
Amended code to read characters rather than lines; so we don't have to wait for a line break before seeing the server's messages.
//using System.Threading.Tasks;
//using System.IO.Pipes;
static void Main()
{
var server = Task.Factory.StartNew(() => RunServer());
var client = Task.Factory.StartNew(() => RunClient());
Task.WaitAll(server, client);
Console.WriteLine("Done");
}
static void RunClient()
{
using (var pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut))
{
Console.WriteLine("Client is waiting to connect");
if(!pipeClient.IsConnected){pipeClient.Connect();}
Console.WriteLine("Client is connected");
using (var reader = new StreamReader(pipeClient))
{
using (var writer = new StreamWriter(pipeClient))
{
var message = string.Empty;
var running = true;
while(running)
{
Console.WriteLine("Client is waiting for input");
var chr = reader.Read();
if (chr >= 32)
{
message = message + (char)chr;
Console.WriteLine("Client: Recieved from server {0}", message);
switch (message)
{
case "Do you accept (y/n):":
writer.WriteLine("y");
writer.WriteLine("quit");
writer.Flush();
break;
case "quit":
running = false;
break;
}
}
else {
message = string.Empty;
Console.WriteLine("Client: New Line Received from Server");
}
}
}
}
}
Console.WriteLine("Client Quits");
}
static void RunServer()
{
using (var pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut))
{
using (var reader = new StreamReader(pipeServer))
{
using (var writer = new StreamWriter(pipeServer))
{
var running = true;
Console.WriteLine("Server is waiting for a client");
pipeServer.WaitForConnection();
Console.WriteLine("Server has connection from client");
Console.WriteLine("Server: Saying Hi");
writer.WriteLine("Hello!");
Console.WriteLine("Server: Prompting for Input");
writer.Write("Do you accept (y/n):"); //NB: This is a write, not a write line!
writer.Flush();
while(running)
{
pipeServer.WaitForPipeDrain();
var message = reader.ReadLine();
Console.WriteLine("Server: Recieved from client {0}", message);
switch (message)
{
case "quit":
writer.WriteLine("quit");
running = false;
break;
default:
writer.WriteLine("");
break;
}
}
}
}
}
Console.WriteLine("Server Quits");
}
So this is what your code should look like:
int charAsInt;
var line = string.Empty;
while(((charAsInt = reader.Read()) != -1)) {
if (charAsInt >= 32) { //is a displayable character
line = line + (char)charAsInt;
//your code to handle the lines
if(line.Contains("Hello!")) {
writer.WriteLine("1.2.3.4"); // input for the next prompt
} else if(line.Contains("Text1") {
writer.WriteLine("2.3.4.5"); // input for next prompt of Text2
}
writer.Flush();
//writer.WaitForPipeDrain();
} else { //is a control character
if (charAsInt == 10 || charAsInt == 13) { //carriage return or line feed; i.e. end of line
if (line.Length > 0) {
Debug.WriteLine("Last line read was {0}", line); //just so you can see info as it comes from the server
line = string.Empty;
}
}
}
}

Async socket server with multiple clients

i have a problem i am unable to resolve as my c# knowledge is not very good.
I found some code on the internet and modified it according to my needs.
My problem is that when i send messages to clients only one receives the message, then the next message is received by another client and so on.
I want to send same message to all connected clients without losing any data.
Server
using System;
using System.Net.Sockets;
using System.Threading;
public class AsynchIOServer
{
static TcpListener tcpListener = new TcpListener(10);
static void Listeners()
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
Console.WriteLine("Client:"+socketForClient.RemoteEndPoint+" now connected to server.");
NetworkStream networkStream = new NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter =
new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader =
new System.IO.StreamReader(networkStream);
////here we send message to client
while (true){
Console.WriteLine("type your message to be recieved by client:");
string theString = Console.ReadLine();
streamWriter.WriteLine(theString);
////Console.WriteLine(theString);
streamWriter.Flush();
}
streamReader.Close();
networkStream.Close();
streamWriter.Close();
}
socketForClient.Close();
Console.WriteLine("Press any key to exit from server program");
Console.ReadKey();
}
public static void Main()
{
//TcpListener tcpListener = new TcpListener(10);
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();
}
}
}
Client:
using System;
using System.Net.Sockets;
using System.Threading;
public class Client
{
static public void Main(string[] Args)
{
TcpClient socketForServer;
try
{
socketForServer = new TcpClient("localHost", 10);
}
catch
{
Console.WriteLine(
"Failed to connect to server at {0}:999", "localhost");
return;
}
NetworkStream networkStream = socketForServer.GetStream();
System.IO.StreamReader streamReader =
new System.IO.StreamReader(networkStream);
System.IO.StreamWriter streamWriter =
new System.IO.StreamWriter(networkStream);
Console.WriteLine("*******This is client program who is connected to localhost on port No:10*****");
try
{
string outputString;
// read the data from the host and display it
{
while (true)
{
outputString = streamReader.ReadLine();
Console.WriteLine("Message Recieved by server:" + outputString);
streamWriter.Flush();
}
}
}
catch
{
Console.WriteLine("Exception reading from Server");
}
// tidy up
networkStream.Close();
Console.WriteLine("Press any key to exit from client program");
Console.ReadKey();
}
private static string GetData()
{
//Ack from sql server
return "ack";
}
}
Thank you
simple working multi-threaded server:
static void Process(Socket client) {
Console.WriteLine("Incoming connection from " + client.RemoteEndPoint);
const int maxMessageSize = 1024;
byte[] response;
int received;
while (true) {
// Send message to the client:
Console.Write("Server: ");
client.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
Console.WriteLine();
// Receive message from the server:
response = new byte[maxMessageSize];
received = client.Receive(response);
if (received == 0) {
Console.WriteLine("Client closed connection!");
return;
}
List<byte> respBytesList = new List<byte>(response);
respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
Console.WriteLine("Client (" + client.RemoteEndPoint + "+: " + Encoding.ASCII.GetString(respBytesList.ToArray()));
}
}
static void Main(string[] args) {
int backlog = -1, port = 2222;
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.ReceiveTimeout = -1;
// Start listening.
try {
server.Bind(new IPEndPoint(IPAddress.Any, port));
server.Listen(backlog);
}
catch (Exception) {
Console.WriteLine("Listening failed!");
Console.ReadKey();
return;
}
Console.WriteLine("Start listening...");
while(true) {
Socket client = server.Accept();
new System.Threading.Thread(() => {
try { Process(client); } catch (Exception ex) { Console.WriteLine("Client connection processing error: " + ex.Message); }
}).Start();
}
//Console.WriteLine("Press any key for exit...");
//Console.ReadKey();
}
And client:
static void WorkWithServer(Socket server) {
const int maxMessageSize = 1024;
byte[] response;
int received;
while(true) {
try {
// Receive message from the server:
response = new byte[maxMessageSize];
received = server.Receive(response);
if (received == 0) {
Console.WriteLine("Server closed connection.");
return;
}
List<byte> respBytesList = new List<byte>(response);
respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
Console.WriteLine("Server: " + Encoding.ASCII.GetString(respBytesList.ToArray()));
// Send message to the server:
Console.Write("You: ");
server.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
Console.WriteLine();
}
catch (Exception ex) {
Console.WriteLine("Error: " + ex.Message);
return;
}
}
}
static void Main(string[] args) {
IPEndPoint serverEp = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 2222);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.ReceiveTimeout = -1;
// Connect to the server.
try { server.Connect(serverEp); }
catch (Exception) {
Console.WriteLine("Establish connection with server (" + serverEp + ") failed!");
Console.ReadKey();
return;
}
Console.WriteLine("Connection with server (" + serverEp + ") established!");
WorkWithServer(server);
Console.WriteLine("Press any key for exit...");
Console.ReadKey();
}
Edit as you need.
Your code is wrong.
First of all I'll give you some insight of how it's wrong and why it's not working the way you want.
You're creating n number of threads, and making them ALL wait for a connection. What if you exhaust the number of threads? What if any of them exits unexpectedly?
You are also sending the data wrong. By using Console.ReadLine you aren't passing the data through multiple threads and reading the line in each one, instead, the first one that calls Console.ReadLine will be the one that's going to receive it. This means you'll only be sending to only one Socket.
It's not ideal how you're managing this. There are dozens if not hundreds of multithreaded socket server/client available online, and I'd invite you to research a little bit more. But first I'd like you to research more about Thread/Task in C#.

C# IRC Bot Error: 'Cannot read from a closed text reader'

I used this code once before, and it worked. Now, every time it tries to connect to an IRC server, I get the error: 'Cannot read from a closed text reader'
I've changed the adresses for privacy
This is my code:
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace IRCBot
{
class Program
{
}
class IrcBot
{
// Irc server to connect
public static string SERVER = "irc.rizon.net";
// Irc server's port (6667 is default port)
private static int PORT = 6660;
// User information defined in RFC 2812 (Internet Relay Chat: Client Protocol) is sent to irc server
private static string USER = "irc_bot";
// Bot's nickname
private static string NICK = "BotNick";
// Channel to join
private static string CHANNEL = "#testing";
// StreamWriter is declared here so that PingSender can access it
public static StreamWriter writer;
static void Main(string[] args)
{
NetworkStream stream;
TcpClient irc;
string inputLine;
StreamReader reader;
string nickname;
try
{
irc = new TcpClient(SERVER, PORT);
stream = irc.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
// Start PingSender thread
PingSender ping = new PingSender();
ping.Start();
writer.WriteLine(USER);
writer.Flush();
writer.WriteLine("NICK " + NICK);
writer.Flush();
writer.WriteLine("JOIN " + CHANNEL);
writer.Flush();
while (true)
{
while ((inputLine = reader.ReadLine()) != null)
{
if (inputLine.EndsWith("JOIN :" + CHANNEL))
{
// Parse nickname of person who joined the channel
nickname = inputLine.Substring(1, inputLine.IndexOf("!") - 1);
// Welcome the nickname to channel by sending a notice
writer.WriteLine("NOTICE " + nickname + " :Hi " + nickname +
" and welcome to " + CHANNEL + " channel!");
writer.Flush();
// Sleep to prevent excess flood
Thread.Sleep(2000);
}
}
// Close all streams
writer.Close();
reader.Close();
irc.Close();
}
}
catch (Exception e)
{
// Show the exception, sleep for a while and try to establish a new connection to irc server
Console.WriteLine(e.ToString());
Thread.Sleep(5000);
string[] argv = { };
Main(argv);
}
}
}
class PingSender
{
static string PING = "PING :";
private Thread pingSender;
// Empty constructor makes instance of Thread
public PingSender()
{
pingSender = new Thread(new ThreadStart(this.Run));
}
// Starts the thread
public void Start()
{
pingSender.Start();
}
// Send PING to irc server every 15 seconds
public void Run()
{
while (true)
{
IrcBot.writer.WriteLine(PING + IrcBot.SERVER);
IrcBot.writer.Flush();
Thread.Sleep(15000);
}
}
}
}
Close all streams must be outside while:
while (true)
{
while ((inputLine = reader.ReadLine()) != null)
{
....
}
}
// Close all streams
writer.Close();
reader.Close();
irc.Close();
Move all your stream closing lines to "finally" block:
try
{
...
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Thread.Sleep(5000);
string[] argv = { };
Main(argv);
}
finally
{
//Close all streams
writer?.Close();
reader?.Close();
irc?.Close();
}
Note, I've used new C#6 null-propagation operator ?. here cause your streams can be null. If you're using C# ver<6 then write it like this:
if (writer!=null) writer.Close();

Categories

Resources