Named pipes app freezing after sending a request to NamedPipeServerStream - c#

I've written some code that uses named pipes to send a string from one application to another. It works fine once, but when the client tries to send the to the server application for a second time it freezes when it tries to connect to the client.
The server code is this:
static void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("MyPipe");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
while (true)
{
var line = reader.ReadLine();
if (line != null)
{
System.Windows.Forms.MessageBox.Show("Data: : " + line);
}
}
});
}
The client code is:
private void Test()
{
using (var client = new NamedPipeClientStream("MyPipe"))
{
client.Connect();
StreamWriter writer = new StreamWriter(client);
writer.WriteLine("INCOMING:1234567");
writer.Flush();
client.Dispose();
}
}
Tracking the code through, I can see that loop in the server code is continuously checking for any lines being read in but not finding any. The client is hanging on the client.Connect() call when the Test() method is called for a second time. No exceptions are raised.
Can anyone see where I'm going wrong?

Your server stays connected to the first pipe instance used to send the first string.
However, your client is disposing its pipe instance after each test, so the second test creates and tries to connect on a new pipe instance, but the server is no longer listening, so the Connect call blocks waiting for a server.
You need to either:
make your server multithreaded, so that it continues listening while servicing instances already connected; or
Refactor your client so that it connects once, then reuses that connected instance.

Following on from what #Chris Dickson answered, I solved my problem with the following code:
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
StreamReader reader = new StreamReader(server);
Boolean connectedOrWaiting = false;
while (true)
{
if (!connectedOrWaiting)
{
server.BeginWaitForConnection((a) => { server.EndWaitForConnection(a); }, null);
connectedOrWaiting = true;
}
if (server.IsConnected)
{
var line = reader.ReadLine();
if (line != null)
System.Windows.Forms.MessageBox.Show("Data: : " + line);
server.Disconnect();
connectedOrWaiting = false;
}
}
});

Related

C# all pipe instances are busy

The following code creates a new thread acting first as a named pipe client for sending parameters and then as a server for retrieving results. After that it executes a function in another AppDomain acting as a named pipe server and after that as a client to send the results back.
public OrderPrice DoAction()
{
Task<OrderPrice> t = Task<OrderPrice>.Factory.StartNew(NamedPipeClient, parameters);
if (domain == null)
{
domain = AppDomain.CreateDomain(DOMAINNAME);
}
domain.DoCallBack(AppDomainCallback);
return t.Result;
}
static OrderPrice NamedPipeClient(object parameters) {
OrderPrice price = null;
using (NamedPipeClientStream stream = new NamedPipeClientStream(PIPE_TO)) {
stream.Connect();
SerializeToStream(stream, parameters);
}
using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_BACK)) {
stream.WaitForConnection();
price = (OrderPrice)DeserializeFromStream(stream);
}
return price;
}
void AppDomainCallback() {
OrderPrice price = null;
using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_TO)) {
stream.WaitForConnection();
List<object> parameters = (List<object>)DeserializeFromStream(stream);
if (mi != null)
price = (OrderPrice)mi.Invoke(action, parameters.ToArray());
}
using (NamedPipeClientStream stream = new NamedPipeClientStream(PIPE_BACK)) {
stream.Connect();
SerializeToStream(stream, price);
}
}
The code is called once per second on average and it worked fine for 7+ hours. But at some point "system.io.ioexception all pipe instances are busy" is thrown and they wont reconnect anymore after that. Browsing here it seems like it could be because of not properly disposing the pipe objects, but I guess thats all good since they are inside using statements.
Does anyone have any clue what could be wrong here? The code is in .NET 4.0 running on windows server 2008.
Sounds like it should be a mutex instead of a simple lock
Lock, mutex, semaphore... what's the difference?
as far as the occasional halting, it could be starvation or a deadlock.
This is good reading material for abstracts on what may be happening
http://en.wikipedia.org/wiki/Dining_philosophers_problem

Getting Windows Store Sockets to chat with Netcat?

I'm trying to do get a basic interface working for Windows Store using the Windows.Networking.Sockets API. So far I have this:
public async void Test()
{
using (var socket = new StreamSocket())
{
socket.Control.KeepAlive = false;
socket.Control.NoDelay = false;
await socket.ConnectAsync(new HostName("192.168.1.1"), "5555", SocketProtectionLevel.PlainSocket);
using (var writer = new DataWriter(socket.OutputStream))
{
writer.UnicodeEncoding = UnicodeEncoding.Utf8;
writer.WriteString("yea!");
//writer.WriteByte(0x50); //this doesn't work either to send raw ASCII
var t = writer.FlushAsync();
while (t.Status != AsyncStatus.Completed) ; //just in case?
}
}
}
So far, I do appear to get a successful connect and disconnect. However, I never get any text received.
My netcat command (running under an OpenBSD router)
$ nc -lv 5555
If I don't have netcat running when I run the Test function, it will throw an exception and all that as well as expected. What am I doing wrong here?
This makes absolutely no sense to me, but apparently StoreAsync is required on the DataWriter. I would've thought that Flush should've called that, but apparently not. Yet another fun part about the WinRT APIs. My fixed code:
using (var socket = new StreamSocket())
{
socket.Control.KeepAlive = false;
socket.Control.NoDelay = false;
await socket.ConnectAsync(new HostName("192.168.1.1"), "5555", SocketProtectionLevel.PlainSocket);
using (var writer = new DataWriter(socket.OutputStream))
{
writer.UnicodeEncoding = UnicodeEncoding.Utf8;
writer.WriteString("yea!");
await writer.StoreAsync();
}
}

C# TcpListener AcceptSocket does not work in separate thread

I have a simple TCP server based on the TcpListener. Since I want to use it in a Windows Form application I made it run in a separate thread as follows:
public void Start() {
this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
this.serverThread.Name = "Tcp-Server";
this.serverThread.Start();
}
protected void ThreadProcess() {
try
{
IPAddress ipAd = IPAddress.Parse("169.254.42.86");
this.listener = new TcpListener(ipAd, this.port);
this.listener.Start();
Socket mySocket = this.listener.AcceptSocket();
while (true)
{
if (mySocket.Connected)
{
byte[] RecvBytes = new byte[8192];
int byteNo = mySocket.Receive(RecvBytes, RecvBytes.Length, 0);
ASCIIEncoding asen = new ASCIIEncoding();
mySocket.Send(asen.GetBytes("srv reply msg"));
}
else
{
WriteLine("socket not connected.");
}
}
}
finally {
StopListener();
}
}
If I use this server in a console application as:
static void Main(string[] args)
{
try
{
int port = 8001;
Server server = new Server(port);
server.Start();
while (true) {
//server is running in separate thread
}
...
everything works as expected. However, when I try to include it in a Windows-Form Application that starts the server when a button is clicked, the code doesn't work any more. The server thread is being launched, but it doesn't accept any sockets.
Is there something that I am missing? I have been searching high and low on google without result...
Thanks for any help!
Not really an answer but too much to type in the comments:
The easiest way to debug this issue is to simply call the ThreadProcess() method in the same thread:
public void Start() {
ThreadProcess();
//this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
//this.serverThread.Name = "Tcp-Server";
//this.serverThread.Start();
}
You can then step through your code to see what happens. As soon as you hit the this.listener.AcceptSocket(); line your application will block, but you should be able to connect to it.
Usually the problem is something silly everyone overlooks like the Start() method not being called.

Network stream problem

I have a server with multiple threads. Here is my server connection:
while (true) {
client = this.tcpListener.AcceptTcpClient();
sThread a = new sThread(form1, listaThreads);
lock(Program.lockThreads) {
listaThreads.Add(a);
}
Thread clientThread =
new Thread(new ParameterizedThreadStart(a.HandleClientComm));
clientThread.Start(client);
}
In my sThread class I have the following code:
public void HandleClientComm(object client)
{
String a = "";
try // nu uita sa pui inapoi!
{
tcpClient = (TcpClient) client;
clientStream = tcpClient.GetStream();
sr = new StreamReader(clientStream);
sw = new StreamWriter(clientStream);
a = sr.ReadLine();
...
But in some cases I get an error at a = sr.ReadLine(); that says the following:
What can it be?
Sometimes remote hosts reboot, or the user kills the client program, or routers reboot losing their state and drop all the connections that they used to carry.
Handling client disconnects is just part of programming reliable software, and you should handle this System.Net.Sockets.SocketException by cleaning up whatever state you have stored for the client and moving on.
Of course, if you also wrote the client software and your users say it is giving similar error messages, then you should investigate further. :)

Program hangs, waiting for input that I can never give

I'm using visual studio to program this small TcpServer.
It's really specific. The server listens to port 1234 and is located on IP 127.0.0.1
Our teachers gave us a program that tries to connect to that port on that IP when you click "connect". It's working for everyone else, so it must be a coding error on my part.
When I click connect, the program sends the word "GET" over the stream, to which I have to respons with a list of allready connected IP-adress and then a newline containing only a .
When I disconnect, the program sends the word "REM" and I simply have to remove if from my list(which is a generic list)
I have a class TCPServer(we had to make our own), which has this as main code:
this.tl = new TcpListener(IPAddress.Any, PORT);
tl.Start();
while(true)
{
TcpClient tcl = tl.AcceptTcpClient();//here the server will wait forever untill someone connects, meaning the "new Thread" statement is never reached untill someone connects.
TcpHelper th = new TcpHelper(tcl,conf);
new Thread(new ThreadStart(th.Start)).Start();//should be multi-threaded, not sure if it is.
//t.Start();
}
TcpHelper looks like this(look for the commented text "here's the problem" within the usings):
public class TcpHelper
{
private TcpClient tc;
private IPEndPoint ipe;
private string get;
private Configuration conf;
public TcpHelper(TcpClient tc, Configuration conf)
{
this.tc = tc;
this.conf = conf;
}
public void Start()
{
using (NetworkStream nws = this.tc.GetStream())
{
using (StreamReader sr = new StreamReader(nws))
{
using (StreamWriter sw = new StreamWriter(nws))
{
this.ipe = (IPEndPoint)tc.Client.RemoteEndPoint;
this.conf.List.Add(this.ipe.Address);
bool conn = true;
while (conn)
{
this.get = sr.ReadLine();//here's the problem
switch (this.get)
{
case "GET":
foreach (IPAddress address in this.conf.Lijst)
{
sw.WriteLine(address.ToString());
}
sw.WriteLine(".");
break;
case "REM":
this.conf.List.Remove(this.ipe.Address);
sw.WriteLine("OK.");
conn = false;
break;
default:
break;
}
}
}
}
}
}
#region Properties
public IPEndPoint Ipe
{
get
{
return this.ipe;
}
}
#endregion
}
My guess is that your problem is that you're calling sr.ReadLine(), but the input does not contain a newline, so it's blocked there waiting for a newline that will never come.
you may want to try calling StreamReader.Read 3 times to build up the command string (GET/REM) before you act on it. (Note: 3 times is because all commands are three characters).
Read will return integers, but after checking that they are not -1 (indicating end-of-file), you can cast that integer to a char.
Sorry, maybe I'm not understanding this... Did you write this code?
this.tl = new TcpListener(IPAddress.Any, PORT);
tl.Start();
while(true)
{
TcpClient tcl = tl.AcceptTcpClient();
TcpHelper th = new TcpHelper(tcl,conf);
new Thread(new ThreadStart(th.Start)).Start();
//t.Start();
}
This is going to blow the **** out of any computer. You're looping infinitely, creating new threads on each loop. So, if you create one new thread per loop, and each loop takes one millisecond (lets say its very slow!), in five seconds you've got 5,000 threads. Each trying to listen at the same port.
Try using a single thread. If this is a console app, use Console.ReadLine() to block the main thread until somebody presses the enter key.
With the new information... AcceptTcpClient blocks, but instead of creating a new thread the work should be queued on the ThreadPool.

Categories