Console App wont stay open, after setting isBackground = true on thread - c#

so I have created a server which needs to listen for clients to connect and in the constructor of my server class I have:
class Server
{
private Thread listenerThread;
private TcpListener listener;
public Server()
{
this.listener = new TcpListener(IPAddress.Any, 5000);
listenerThread = new Thread(ListenMethod) { IsBackground = true };
listenerThread.Start();
}
private void ListenMethod()
{
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
}
}
}
but when I created the instance of server in my main like so:
class Program
{
static void Main(string[] args)
{
Server s = new Server();
}
}
The server should stay open cause of the ListenMethod running and the while loop, yet the program seems to complete the constructor and closes the program.
Any ideas?
Thanks :)

Background threads will not keep a console application alive, as is their purpose. The Server class instance is also going out of scope because it isn't used by anything; in a Release build of this application it might not even be compiled into the application and optimised away. You need to do something like this:
static void Main(string[] args)
{
Server server = new Server();
Console.Write("The server is running. Press any key to stop the server.");
Console.ReadKey();
server.Stop();
}

It doesn't look like you are instantiating your listner instance, before you call Start(), so the code is probably crashing on listener.Start() due to a NullReferenceException
I would expect something like this:
private void ListenMethod()
{
listener = new TcpListener();
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
}
}

Related

Background thread still listening on TCP port after service stopped

I'm writing a C# service (.NET 4.0) which listens on a TCP port. I start the TcpListener on a background thread (using Task Parallel Library) so the service is not unresponsive to Windows. I also use TPL whenever a client connects, as each client will do some database work and I don't want to block other clients.
I install and uninstall the service using InstallUtil.exe on Windows Server 2012 R2 Standard. Whenever I stop the service and uninstall it, using netstat -abo I can see the port is still being listened to by the [System] process. It has a PID, however I can't see a process with this PID in Task Manager or tasklist, nor can I kill it with taskkill. It just says process not found, but it's always there when I run netstat -abo. If I try to start the service again using the same port, I get a socket exception:
Only one usage of each socket address (protocol/network address/port) is normally permitted
Stacktrace:
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at System.Net.Sockets.TcpListener.Start(Int32 backlog)
I'm guessing my background threads are still hanging around after I stop the service, but I have no idea how to kill them now, and how to prevent this from happening. Here is what I hope is the relevant code (deleted exception handling and logging for easier reading):
public partial class MyService : ServiceBase
{
private static TCPServer server = null;
protected override void OnStart(string[] args)
{
server = new TCPServer();
}
protected override void OnStop()
{
if (server != null)
{
server.StopServer();
}
}
}
class TCPServer
{
public static TcpListener listener = null;
private static Task listenerTask = null;
private static List<Task> clientTasks = new List<Task>();
public TCPServer()
{
listenerTask = new Task(() => StartServer());
listenerTask.Start();
}
public void StopServer()
{
foreach(Task task in clientTasks)
{
task.Dispose();
}
listenerTask.Dispose();
if (listener != null)
{
listener.Stop();
listener = null;
}
}
private void StartServer()
{
Int32 port = 51987;
IPAddress localAddr = GetLocalIP();
listener = new TcpListener(localAddr, port);
listener.Start();
while (listener != null)
{
if (listener.Pending())
{
TcpClient client = listener.AcceptTcpClient();
Task task = new Task((obj) => ProcessClient(obj), client);
task.Start();
clientTasks.Add(task);
}
}
}
private void ProcessClient(object obj)
{
using (TcpClient client = obj as TcpClient)
{
Byte[] bytes = new Byte[2048];
String data = null;
NetworkStream stream = client.GetStream();
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = Encoding.ASCII.GetString(bytes, 0, i);
}
// do some stuff with data
// If an exception is thrown here, the rogue thread issue happens when I stop the service.
// Otherwise, everything is good - I stop the service and no rogue thread, I can reuse the listener port.
}
}
}
EDIT:
Updated the code with suggested changes. I've also discovered that this rogue thread issue only seems to occur if an exception is thrown in one of my client threads. If everything runs ok, there is no rogue thread when I stop the service.
"Stop" method, in this case, means stoping the current connection and start listening to a new one so make sure your client is closed properly so that a new connection is not created.
The Stop method also closes the underlying Socket and creates a new
Socket for the TcpListener. If you set any properties on the
underlying Socket prior to calling the Stop method, those properties
will not carry over to the new Socket.
https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.stop(v=vs.110).aspx#
Moreover, make sure you use using with the client
using(TcpClient client = obj as TcpClient){//DO SOMETHING}

C# server.AcceptTcpClient and Listbox

I'm writing a simple TCP-Connection software.
Firstly, I wrote the server in a ConsoleApp and it workes quite well.
Now I wanted to port it to a form application, but when a client connects, it does not add a new entry in my ListBox, on the Console it workes well.
I tried to write in the Load function as well as writing it in a separate Thread.
Both don't work.
In the Console it worked like this, and the Console wrote "User connected":
static void Main(string[] args)
{
const int PORT = 14758;
TcpListener server = new TcpListener(IPAddress.Any, PORT);
try
{
server.Start();
Console.WriteLine("Server started");
} catch (Exception Ex)
{
Console.WriteLine("Error", Ex);
}
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("User connected");
Now in my form App it does not work like this:
public frmMainServer()
{
InitializeComponent();
Thread serverStart = new Thread(new ThreadStart(start_Server));
serverStart.Start();
serverStart.Join();
TcpClient client = server.AcceptTcpClient();
addItem("User connected");
}
As said before, I tried to write the last 2 lines in the Thread, too, but it didn't help.
I actually think I CAN connect to the server, so why does it not add the line?
addItem function:
private void addItem(string item)
{
_items.Add(item);
listStatus.DataSource = _items;
}

Socket Feeder Exits

I have an console application, which waits for client to be connected specified socket, after that accepts client, starts feeding data, if after a while client application stops, distributer exit itself, but I would make distributer just change mode in listen for client, when client connection lost, distributer just start for waiting but meanwhile exits.
static class Program
{
static void Main()
{
Start()
}
}
private void Start()
{
WaitForClientConnection();
//waits till client connect
StartReceive();
}
private void WaitForClientConnection()
{
_tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_tcpSocket.Bind(new IPEndPoint(IPAddress.Parse("172.16.192.40"), 7000));
_tcpSocket.Listen(100);
_tcpClientAcceptSocket = _tcpSocket.Accept();
}
public void StartReceive()
{
try
{
Console.WriteLine("Starting to receive data...");
while (_tcpClient.Connected)
{
//sendind data to client
}
if (!_tcpClient.Connected)
{
// if client socket listener is stops somehow, I also close _tcpClient connection after that start to keep waiting for clients
Console.WriteLine("Closing the connection...");
_tcpClient.Close();
//here start(), and WaitForClientConnection() are begin again(I realized and sure) however in WaitForClientConnection() function exits itself from application not wait for client
Start();
}
}
}
What could be the problem ?
thanks
When you invoke WaitForClientConnection() the second time, you try to bind a new listening socket to 172.16.192.40:7000. You already have a socket bound to that address, from the first invocation of WaitForClientConnection().
Try something like this:
private void CreateListener()
{
_tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_tcpSocket.Bind(new IPEndPoint(IPAddress.Parse("172.16.192.40"), 7000));
_tcpSocket.Listen(100);
}
private void Start()
{
if (_tcpSocket == null)
{
CreateListener();
}
WaitForClientConnection();
//waits till client connect
StartReceive();
}
private void WaitForClientConnection()
{
_tcpClientAcceptSocket = _tcpSocket.Accept();
}
Really you could get rid of WaitForClientConnection entirely, since it's now a single line of code. But then this is not how I'd write this; I was just trying to stay close to your original code.
The key point is that you create the listening socket once. It doesn't go away when you accept a conversation.
I don't know if this is the only issue. You should be catching and reporting exceptions, so we'd know exactly what was terminating the process.

Synchronizing collections and aborting tasks

I am writing a small multi-threaded network server. All classical stuff: it listens for incoming connections, accepts them and then serves them in different threads. Also, this server sometimes will have to restart, and to do so it must a) stop listening, b) kick out all connected clients, c) adjust some settings/wait, d) resume listening.
Well, I pretty much don't know a thing about developing multi-threaded programs, so I am looking for help. Here's what I came to (core stuff only):
class Server
{
class MyClient
{
Server server;
TcpClient client;
bool hasToFinish = false;
public MyClient(Server server, TcpClient client)
{
this.server = server;
this.client = client;
}
public void Go()
{
while (!hasToFinish)
{
// do all cool stuff
}
CleanUp();
}
private void CleanUp()
{
// finish all stuff
client.Close();
server.myClients.Remove(this);
}
public void Finish()
{
hasToFinish = true;
}
}
bool running = false;
TcpListener listener;
HashSet<MyClient> myClients = new HashSet<MyClient>();
public void Start()
{
if (running)
return;
myClients.Clear();
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
listener.Start();
listener.BeginAcceptTcpClient(AcceptClient, this);
running = true;
}
public void Stop()
{
if (!running)
return;
listener.Stop();
foreach (MyClient client in myClients)
{
client.Finish();
}
myClients.Clear();
running = false;
}
public void AcceptClient(IAsyncResult ar)
{
MyClient client = new MyClient(this, ((TcpListener)ar.AsyncState).EndAcceptTcpClient(ar));
myClients.Add(client);
client.Go();
}
}
It's absolutely unsatisfactory. There is no sychronizing (I just don't know where to put it!), and calling Server.Stop() doesn't make MyClient-s to stop immediately. How do I fix these problems?
The code looks quite clean, we can make it thread-safe with simple modifications.
There are three parts of the problem, the "client", the "server" and the client-server interaction.
Client first, the Go() method is invoked by one thread (let's call it A) and the Finish() method is invoke by another thread (B). When thread B modify hasToFinish field, thread A may not see the modification immediately because the variable may be cached in the CPU cache. We can fix it by making hasToFinish field "volatile", which force thread B to publish the variable change to thread A when update.
Now the server class. I recommend you to synchronise three methods on the "Server" instance like the example below. It makes sure Start and Stop are called sequentially and the variables they changes are published across threads.
The client-server interaction need to be addressed as well. In your code, Client remove its reference from the Server but the server clear all clients references when Finish() any way. It looks redundant to me. If we can remove the part of code in client, we have nothing to worry about. If you choose to keep the logic in the client rather in the server for what ever reason, create a public method call RemoveClient(Client client) in the Server class and synchronise it against the Server instance. Then let the client to invoke this method instead of manipulating the HashSet directly.
I hope this solve your problem.
public void Start()
{
lock(this)
{
if (running)
return;
myClients.Clear();
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1234);
listener.Start();
listener.BeginAcceptTcpClient(AcceptClient, this);
running = true;
}
}
public void Stop()
{
lock(this)
{
if (!running)
return;
listener.Stop();
foreach (MyClient client in myClients)
{
client.Finish();
}
myClients.Clear();
running = false;
}
}
public void AcceptClient(IAsyncResult ar)
{
lock(this)
{
MyClient client = new MyClient(this, ((TcpListener)ar.AsyncState).EndAcceptTcpClient(ar));
myClients.Add(client);
client.Go();
}
}

how to setup a tcplistener in windows services c#

Iam beginner to windows services , i have a console application to transfer files between client and server . Now i would like to turn my server application into windows services for listening multiple clients . I placed my console application code inside onstart() . After deploying the windows services not working or listening . Any IQ's...
Here is a complete article on TCP listener in windows service. It's quite old though but may be it helps.
hi i know this question is a long-standing one, and i checked many articles on stackoverflow or other sites, but there is no one make me satisfied. the most headache point is: it is a windows service, the while loop of listener should NOT be blocked when the service startup.
finally i made up a solution by myself, maybe maybe it is not system friendly, but it is quite simple and works fine ( I opened 3 telnet to this server concurrently, and it works as i wish) :-)
here is the code:
`protected override void OnStart(string[] args)
{
tcpServerStart();
}
private void tcpServerStart()
{
try
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
//port 5555, or any port number you want
listener = new TcpListener(ipAddress, 5555);
listener.Start();
var whileThread = new Thread(() =>
{
while (true)
{
// in order to avoid while loop turn into an infinite loop,
// we have to use AcceptTcpClient() to block it.
TcpClient client = listener.AcceptTcpClient();
// for each connection we just fork a thread to handle it.
var childThread = new Thread(() =>
{
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream(); // not blocking call
StreamReader streamreader = new StreamReader(client.GetStream(), Encoding.ASCII);
string line = null;
// below while loop is your logic code, change it to your needs.
// defined "<EOF>" as mine quit message
while ((line = streamreader.ReadLine()) != "<EOF>")
{
// WriteToFile is a function of mineto log system status
WriteToFile(line);
}
stream.Close();
client.Close();
});
childThread.Start();
} // end of while(true) loop
});
whileThread.Start();
}
catch (Exception e)
{
}
} '
this server open thread else never running service
protected override void OnStart(string[] args)
{
TcpServer server=new TcpServer();
server.Start();
}
class TcpServer
{
// clase prar crear un listener
private TcpListener server;
private bool isRunning;
private int port = 13000;
public void Start()
{
// client found.
// create a thread to handle communication
Thread tServer = new Thread(new ParameterizedThreadStart(StartThread));
tServer.Start();
}
public void StartThread(object o)
{
//iniciar configuraciones
Configuracion.init();
// crear un nuevo servidor
server = new TcpListener(IPAddress.Any, port);
//inicializar el servidor
server.Start();
//variable para indicar queesta corriendo el server
isRunning = true;
LoopClients();//thread
}}
public void LoopClients()
{
while (isRunning)
{
// wait for client connection
TcpClient newClient = server.AcceptTcpClient();
// client found.
// create a thread to handle communication
Thread t = new Thread(new ParameterizedThreadStart(HandleClient));
t.Start(newClient);
}
}

Categories

Resources