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.
Related
I searched foe the solution but could not get it.
Here is the code for windows service.
protected override void OnStart(string[] args)
{
Debugger.Launch();
try {
AsynchronousSocketListener.StartListening();
// Log an event to indicate successful start.
EventLog.WriteEntry("Successful start.", EventLogEntryType.Information);
}
catch(Exception ex)
{
// Log the exception.
EventLog.WriteEntry(ex.Message, EventLogEntryType.Error);
}
}
Here is the class AsynchronousSocketListner
static string constr = "Integrated Security=SSPI;Persist Security Info=False;Data Source=WIN-OTVR1M4I567;Initial Catalog=CresijCam";
//string test = constr;
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
private AsynchronousSocketListener()
{
}
public static void StartListening()
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1200);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(200);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
string me = e.Message;
}
}
I am getting different Error messages everytime:
A timeout (30000 milliseconds) was reached while waiting for a transaction response from the TCPService service.
Service cannot be started. The service process could not connect to the service controller
I dont know from where is the error that I am getting is coming. I know one thing that service is not run yet. and It is in this method startListening(). I debugged using Debugger.launch(). But I am not getting to a specific line .
I also think this is related to TCP somewhere but nothing for sure.
The same code is in working state for console Project.
I dont know what other code to put here. But please let me know if needed further detail.
This simple answer is your AsynchronousSocketListener is not Asynchronous or threaded or anything of the sort. Essentially your service Start is timing out, and will never hit
EventLog.WriteEntry("Successful start.", EventLogEntryType.Information);
Because it is essentially blocking forever
This error says it all
A timeout (30000 milliseconds) was reached while waiting for a
transaction response from the TCPService service.
OnStart should only start the work. This typically means spawning a new thread to do the actual work. In short, it is expected that OnStart completes promptly.
You will need to refactor your code to run your AsynchronousSocketListener in a new thread or task
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}
I am working on creating a custom TCP/IP client/server application, and have run into a snag when attempting to stop the server. Originally, my code used one TcpListener to listen on a designated port, and my (simplified for convenience) code to start and stop the server went as follows:
private bool state;
private TcpListener listener;
private CancellationTokenSource tokenSource;
private Dictionary<string, ConnectedClient> clients;
private List<Task> clientTasks;
private ConnectedClient command_client;
public async Task RunServer() {
if (!state) {
state = true;
tokenSource = new CancellationTokenSource();
listener = new TcpListener(IPAddress.Any, 55001);
listener.Start();
while (true) {
try {
TcpClient socketClient = await listener.AcceptTcpClientAsync();
ConnectedClient client = new ConnectedClient(socketClient);
clients.Add(client.id, client);
client.task = ProcessClientAsync(client, tokenSource.Token);
clientTasks.Add(client.task);
}
catch (ObjectDisposedException) {
//Server stopped by user
//exit while
break;
}
}
/* Server has been stopped; close all connections */
CloseAll();
}
else {
/* Stop the server */
tokenSource.Cancel();
listener.Stop();
/* Clean up of currently connected clients is handled in CloseAll, handled upon ObjectDisposedException above */
}
}
ConnectedClient is a class I wrote to hold some info about individual clients for convenience and has a function that handles what happens when data is received. I realize I left some things out to streamline, but this code does exactly what I want it to do: the server waits for connections, creates a ConnectedClient object to handle connections received, and goes back to waiting. When this function is called when the server is already listening, the listener is stopped, which causes the listener to throw an exception, which breaks the loop and closes all connections.
The snag occurs when I attempted to create a server that listens on two different ports, which need to be treated differently.
Here is my code for (attempting) that:
private bool state;
private Dictionary<string, ConnectedClient> clients;
private TcpListener command_listener;
private TcpListener query_listener;
private CancellationTokenSource tokenSource;
private List<Task> clientTasks;
public async Task RunServer() {
if (!state) {
state = true;
tokenSource = new CancellationTokenSource();
command_listener = new TcpListener(IPAddress.Any, 55001);
command_listener.Start();
query_listener = new TcpListener(IPAddress.Any, 55002);
query_listener.Start();
Task prevCommand = null;
Task prevQuery = null;
while (true) {
try {
if (prevCommand == null || prevCommand.IsCompleted) {
prevCommand = waitForConnections(command_listener);
}
if (prevQuery == null || prevQuery.IsCompleted) {
prevQuery = waitForConnections(query_listener);
}
await Task.WhenAny(prevCommand, prevQuery);
}
catch (ObjectDisposedException) {
//Server stopped by user
//exit while
break;
}
}
/* Server has been stopped; close all connections */
CloseAll();
}
else {
/* Stop the server */
tokenSource.Cancel();
command_listener.Stop();
query_listener.Stop();
/* Clean up of currently connected clients is handled in CloseAll, handled upon ObjectDisposedException above */
}
}
The purpose of waitForConnections is to handle connection requests so that waiting for a connection on one port doesn't block connections on the other, and also to ensure that only one connection can be made on port 55001.
public async Task waitForConnections(TcpListener listener) {
TcpClient socketClient = await listener.AcceptTcpClientAsync();
if (((IPEndPoint)listener.LocalEndpoint).Port == 55001 ) {
if (command_client == null) {
command_client = new ConnectedClient(socketClient, onClientUpdate, onResend);
clients.Add(command_client.id, command_client);
command_client.task = ProcessClientAsync(command_client, tokenSource.Token);
clientTasks.Add(command_client.task);
}
else {
//only one client allowed on this port, reject the connection
socketClient.Close();
}
}
else {
ConnectedClient client = new ConnectedClient(socketClient, onClientUpdate, onResend);
clients.Add(client.id, client);
client.task = ProcessClientAsync(client, tokenSource.Token);
clientTasks.Add(client.task);
}
}
With this, I am able to connect clients on the two ports without blocking, but calling this function again and stopping the listeners does not seem to cause a ObjectDisposedException to be thrown as expected, which causes the whole program to hang and not do anything. I suspect this is being caused by some irresponsible use of asynchronous functions, but how can I fix it?
Because the await listener.AcceptTcpClientAsync() call is inside an async task instead of directly inside the loop, the exception that occurs when the listener is stopped causes the task to return with a status of "Faulted". Because the exception isn't caught, the loop continues, and a faulted task is considered a completed task, so it goes right back to trying to listen for connections despite the stopped listener (which in turn most likely causes the task to fault again).
Could have fixed this by checking for faulted tasks instead of catching the exception, but I instead chose to set a flag when I try to stop the server that breaks the loop and allows the program to close connections as intended.
I want to wait for 10 sec before that the server accept connexion of a client, i ve been looking in the net but i did not find an example,
this is the code i wrote , is there anyone who could give a solution for that, thanks a lot:
class Program
{
// Thread signal.
public static ManualResetEvent tcpClientConnected = new ManualResetEvent(false);
// Accept one client connection asynchronously.
public static void DoBeginAcceptTcpClient(TcpListener listener)
{
// Set the event to nonsignaled state.
tcpClientConnected.Reset();
// Start to listen for connections from a client.
Console.WriteLine("Waiting for a connection...");
// Accept the connection.
// BeginAcceptSocket() creates the accepted socket.
listener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClientCallback),listener);
// Wait until a connection is made and processed before
// continuing.
tcpClientConnected.WaitOne(10000);
}
// Process the client connection.
public static void DoAcceptTcpClientCallback(IAsyncResult ar)
{
// Get the listener that handles the client request.
TcpListener listener = (TcpListener)ar.AsyncState;
// End the operation and display the received data on
// the console.
TcpClient client = listener.EndAcceptTcpClient(ar);
// Process the connection here. (Add the client to a
// server table, read data, etc.)
Console.WriteLine("Client connected completed");
// Signal the calling thread to continue.
tcpClientConnected.Set();
}
static void Main(string[] args)
{
Int32 port = 1300;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(localAddr, port);
listener.Start();
while (true)
{
DoBeginAcceptTcpClient(listener);
}
}
}
I really don't want to know why you'd want this, but simply waiting before ending the accept will do that:
// Process the client connection.
public static void DoAcceptTcpClientCallback(IAsyncResult ar)
{
// Get the listener that handles the client request.
TcpListener listener = (TcpListener)ar.AsyncState;
// Wait a while
Thread.Sleep(10 * 1000);
// End the operation and display the received data on
// the console.
TcpClient client = listener.EndAcceptTcpClient(ar);
// ...
}
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();
}
}