Re attach Socket - c#

So I have a socket server running, inside an asp.net ( C# ) application (very bad approach) that notifies any device connected,
It was like that when I started working at this company and changing it is not on a priority to my supervisors even though it will be better.
So what happens is when we do an update to the Website the Socket connection stays open (in another thread), then we have to restart the Server, but what I want to do is somehow get the Thread ID on startup of the Socket, then store it, if the update is done it should reattach to that thread and end the Socket somehow or reset it.
Is this possible?
this is sample code
private void Start()
{
_socketServer = new TcpListener(IPAddress.Any, Convert.ToInt32(ConfigurationManager.AppSettings["NotificationSocketPort"]));
_socketServer.Start();
_acceptingThread = new Thread(() =>
{
while (true)
{
try
{
var client = _socketServer.AcceptTcpClient();
StartClient(client);
}
catch (ObjectDisposedException ex)
{
_acceptingThread = null;
_socketServer = null;
Start();
break;
}
}
});
_acceptingThread.Start();
}
public void Close()
{
if (_acceptingThread != null)
{
_acceptingThread.Abort(0x0);
_socketServer.Stop();
_acceptingThread = null;
_socketServer = null;
}
}
In global.asax
protected void Application_End(object sender, EventArgs e)
{
SocketNotifier.GetNotifierInstance().Close();
}
The SocketNotifier is using the Singleton Design Pattern

Frankly, this is just the wrong approach. Web apps restart, and should be expected to restart. Sockets don't like that, and should not be expected to like that. Your best bet here would be to re-write the socket code as a windows service - that way it can keep running independently of the web-app.

They [the sockets] stay open that is the problem after IIS worker process terminates and a new one is started
Probably, IIS has trouble shutting down the old process. That keeps the socket open. Your socket thread is a foreground thread. It does not prevent process termination. Also, aborting a thread does not affect IO. And your socket listening method automatically restarts itself when the socket is closed.
Remove these problems. Make the thread a background thread. Don't abort it. Don't restart it in case of an ObjectDisposedException.

Related

Running a WCF Duplex Web Service Client under a new message loop thread

I need to run a WCF duplex client connection under a new message loop in a thread, so far I’ve implemented the following:
public class RoomOpen
{
public static bool Main(Data oSystem)
{
Thread STA5050Thread = new Thread(() =>
{
Application.Run();
var oring = new FXBackgroundLoader(oSystem.GetSystem());
});
STA5050Thread.SetApartmentState(ApartmentState.STA);
STA5050Thread.IsBackground = true;
STA5050Thread.Start();
return true;
}
}
The problems here are:
A - The client connection that should start under FXBackgroundLoader() is never called, this connection is made and then pings sent continually so the thread should start and stay open.
B - The application returns true almost immediately.
What I need in the end is a WCF duplex client connection which can run under a new message loop on the current thread but keep the thread open without blocking it.
One way I've previously had success with is to open a Windows form under Application.Run(new form()) and then pop all the code for the client connection in the form, that works fanatically but is no longer a possibility due to additional changes in my project.
Does anyone have any idea what the issue is with my implementation and/or how I might better implement what I require?

C# program hangs on Socket.Accept()

I created a server "middleman" application that uses sockets and multi-threading techniques (ServerListener is run in a new thread). I found early on that when I would use the Socket.Accept() method, the program would hang indefinitely, waiting for that connection to happen. The problem is, as far as I can tell there is no reason for it not to.
I spent a good portion of the day trying lots of different things to make it work, and somewhere something changed because it suddenly started working for a while. However, as soon as I accidentally chose a different data source than "localhost" for the client application, the problem popped back up again. I have tried running the program without the firewall OR antivirus running, but no luck. The client program IS set to connect on port 10000. Here is my code:
public void ServerListener() {
UpdateStatus("Establishing link to server");
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, defaultPort));
server.Listen(queue);
UpdateStatus("Accepting Connections");
while (true) {
Socket client = default(Socket);
try {
client = server.Accept();
if (client != null) {
++count;
UpdateCount(count.ToString());
new Thread(
() => {
Client myclient = new Client(client, defaultPort, this);
}
).Start();
}
}
catch( Exception ex ){
MessageBox.Show(ex.ToString());
client.Close();
}
}
}
It will run just fine right up until server.Accept(), then hangs. As stated, it did work for a while earlier, but is now hanging again. I've tried to see if any other programs are using port 10000, and they aren't. I went over and over this with a friend, and we couldn't find the problem. Please help!
EDIT To be clear, I do know that Accept is a blocking call. The client program makes the connection on port 10000, but this program keeps on waiting on the Accept as if nothing happened. It did work for a time, so I know the connection is working like it is supposed to from the client program's end. However, I can't fathom why this program is now acting like that connection never happens, and continues to wait on the Accept.
Accept blocks on purpose. If you want to do other things while waiting for another client to connect you can:
Run the ServerListener in another Thread or better - a long running task:
using System.Threading.Tasks;
...
Task.Factory.StartNew(ServerListener, TaskCreationOptions.LongRunning);
Use the AcceptAsync method which uses the SocketAsyncEventArgs class. For that to work, you create a new SocketAsyncEventArgs instance, set its values and pass it to socket.AcceptAsync.

C#: System.Net.Sockets.TcpListener is sometimes not closing Socket properly

in one of my projects I have implemented a small HTTP server to stream the video data of a connected webcam. For this task I'm utilizing the System.Net.Sockets.TcpListener from .NET Framework 4.5, which listens to a pre-configured endpoint and uses the AcceptSocketAsync() mtehod to wait for incomming requests. You can see the relevant code parts below:
this.server = new TcpListener(endpoint);
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 0));
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.server.Start();
...
this.listenTask = Task.Factory.StartNew(this.Listen);
...
private async void Listen()
{
try
{
while (this.server.Server.IsBound)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Factory.StartNew(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
This works fine, when I start the application and the HTTP server is started for the first time. However, when I stop the HTTP server (done via CheckBox in the settings of the application) the unverlying listening socket is sometimes not closed. When I check for the state of the sockets via console (netstat -ano) I can see that the socket is still in state LISTENING. The resulting problem is, when I restart the HTTP server again I get an System.Net.Sockets.SocketException with the message "Only one usage of each socket address is normally permitted", which is not surprising.
The relevant code part for stopping the HTTP server is as follows:
...
if (this.server != null)
{
if (this.server.Server != null)
{
if (this.server.Server.Connected)
{
this.server.Server.Shutdown(SocketShutdown.Both);
this.server.Server.Disconnect(true);
}
this.server.Server.Close();
}
this.server.Stop();
}
...
I also keep track of my open connections and close them after finishing the transmission of data and when stopping the server. None of the connection sockets stays opened, so I believe only the listening socket should be relevant for this problem.
I already tried various combinations/orders of the Shutdown(), Disconnect(), Close() and Stop() methods when stopping the server, as well as setting/unsetting several options when starting the server like Linger and ReuseAddress, which sometimes seemed to fix the problem at first, but then a few days later the problem occurred again.
I also tried to "force" the listening socket to close when stopping the server using GetTcpTable(...) and SetTcpEntry(...) from iphlpapi.dll, as described in this question: How to close a TCP connection by port?
Unfortunately, this approach did not work for me (it change anything about the state of the listening socket at all).
As I'm a little bit clueless of what else I could do, I'm asking here if somebody has an idea of what might cause the discribed problem or how to solve it. Any help would be greatly appreciated.
Kind regards,
Chris
You should almost always leave TcpListener.Server alone. It's there so you can set socket options on it, not use it for control purposes.
So your Listen should be:
private async void Listen()
{
try
{
while (true)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Run(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
(assuming you do actually want one thread per client, an architecture I do not recommend in general).
When you're ready to stop, just stop:
if (this.server != null)
{
this.server.Stop();
}
If you do not have any special requirement, it is suggested to make use of TcpListener class and its methods only or if you have such requirement, do not use TcpListener and start with the Raw socket.
TcpListener class is self sufficient to provide method like
Start(), AcceptTcpClient() and Stop().
You can create a List<TcpClient> and loop through each client and call client.close() after calling Stop() on the TcpListener instance.
A very good example of client server communication is on MSDN:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx
Regards
On server socket, shutdown & disconnect is not needed for listening sockets. Those calls are needed only for connected sockets. Replace the socket stop with below code:
if (this.server != null)
{
if (this.server.Server != null)
{
this.server.Server.Close();
this.server.Server = NULL;
}
}
I would dispose of your socket connections once you have closed them. The documentation says they should be disposed after closed but personally I like to say when to dispose of anything that use the IDisposable interface.

Method called twice in same moment

I'm working on a windows forms application and fighting with a very harsh error. The application is supposed to run on a local machine and handle requests form a server applicaton. The client application looks like this:
public Reader mr_obj;
public Form1()
{
mr_obj = new MyReader.Reader(7137);
mr_obj.UserEvent += new ReaderEvent(UserEvent);
}
private void UserEvent(UserEvent e, long threadID)
{
Thread.Sleep(1000);
SafeSomethingToDB();
}
The Reader() object is connecting the client application to the server application. So after this, the server application is able to trigger the UserEvent() method in the client application. Ther problem is now, that the client application, which handles the UserEvents, crashes if the UserEvent() method gets triggered twice within one second.
(Its actually not crashing just hanging untill you kill the task, a try catch wont return an error)
What I've tried so far is to delegate the Thread.Sleep() and SafeSomethingToDB() to another thread. This doesnt work because the server application does not wait until the tread is finished. So the server application does not find the data in the DB because its not waiting 1 second...
The same problem happens when I did that with background workers.
Is there a possibility to handle these two triggers, which come from the same server application, in sort of a parallell way at the same time?
Any suggestions very apreciated
EDIT: I think locking the method does not cause the application to process both triggers in the same time. To make this visible I'v tried this:
private void UserEventHandler(UserEvent e, long threadID)
{
lock (_lockObject)
{
MessageBox.Show("Messagebox 1");
MessageBox.Show("Messagebox 2");
}
}
When the first request triggers UserEvent() "MessageBox1" appeares. If you press OK, "MessageBox2" appeares. But if the UserEvent gets triggered a second time while "Messagebox2" is still opened, "MessageBox1" does not appear. Instead of that the application start hanging. Shouldn "MessageBox1" appear again triggered by the second trigger of UserEvent() when the two triggers really ar bbeing processed at the same time? So the two triggers are not beeing preformed parallel or am I mistaking here?
Without knowing why you do the Sleep or what exactly SafeSomethingToDB does and what causes your problems, try to synchronize the calls:
private readonly object _lockObject = new object();
private void UserEvent(UserEvent e, long threadID)
{
lock(_lockObject)
{
Thread.Sleep(1000);
SafeSomethingToDB();
}
}
I think a simple lock for synchronization will work for you, try this
public Reader mr_obj;
private static readonly object sync = new object();
public Form1()
{
mr_obj = new MyReader.Reader(7137);
mr_obj.UserEvent += new ReaderEvent(UserEvent);
}
private void UserEvent(UserEvent e, long threadID)
{
lock(sync)
{
SafeSomethingToDB();
}
}
As you write in the comments, if SafeSomethingToDB() is called a second time before the first call has finished, then it crashes. So in other words: SafeSomethingToDB() is not re-entrant.
What you can do is use a Mutex (which stands for mutual exclusion), which defines a "critical section" in your code, meaning a code that can have only one thread executing it at any one time.
For instance:
private static Mutex mutex = new Mutex();
public void SafeSomethingToDB()
{
mutex.WaitOne(); // wait until it is safe to enter the critical section
// Critical section begins here
DoWorkAndStuff();
mutex.ReleaseMutex(); // indicate the end of the critical section
}
For more about System.Threading.Mutex, see http://msdn.microsoft.com/en-us/library/system.threading.mutex(v=vs.110).aspx.

Connecting to a database on a different thread

I have a WPF application where the user enters database information in some textboxes. Once the user clicks "connect", a connection string is created from what the user had entered and a connection is established. I noticed that if the user enters any info that is wrong, the application will hang until the connection times out. By hang, I mean the user can't interact with the rest of the application at all.
It is my goal to keep the application responsive while the connection string is tested.
I thought that putting this workflow on a different thread is a good solution. My idea is to just disable anything that may need a database connection while the thread runs. Once the thread comes back (and has has confirmed the connection string to be valid) I would re-enable everything. Otherwise, leave everything disabled.
However, the Thread class doesn't have an event notification when the thread is done (or at least I am unaware of one).
I have also worked with the BackgroundWorker class. This works better. However, when the RunWorkerCompletedEventHandler event is fired and the connection string isn't valid, I get the following exception:
The calling thread cannot access this object because a different
thread owns it.
This is probably because the connection still hasn't timed out when the completed event handler is fired.
Does anybody have any ideas, or should I just NOT try to multithread a connection to a database?
A code outline of what I am doing:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
dbTool = new DBTool();
// Create the connection string
e.Result = dbTool.connectToDB(); // connectToDB() returns a bool (true if connection established)
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// connectToDB() returns a bool (true if connection established)
if(e.Result == true) // Trying to read e.Result here throws the exception
{
// e.Error and e.Cancel should be checked first
// However, I would like the thread to finish before
// this event is fired
}
if (e.Error != null)
{
Console.WriteLine(e.Error.Message);
}
}
Don't preserve your DbConnection object in a single global variable and share it between threads.
The .NET environment will automatically pool your connections and share them, so calling new DbConnection() is very fast.
You should keep the connection string in a global variable, but then create connections as required on each thread.
EDIT: The original poster may have actually wanted ideas on how to keep the WinForms application responsive while a connection string is being tested. In that case, you want to spawn a different thread to test the connection. From the "connection test thread," you can update the UI by following this pattern - How to update the GUI from another thread in C#?
public void TestConnectionThread(String connstr_to_test)
{
// Notify the user that we're doing our test
string message = "Testing...";
lblTestResultMessage.SetPropertyThreadSafe(() => lblTestResultMessage.Text, message);
try {
dbTool = new DBTool();
message = dbTool.connectToDB();
// If something failed, show a useful debugging message
} catch (Exception ex) {
message = ex.ToString();
}
// Use a lambda expression to communicate results to the user safely
lblTestResultMessage.SetPropertyThreadSafe(() => lblTestResultMessage.Text, message);
}
From DBConnection's documentation:
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
In other words, different threads should never share a database connection, because the instance cannot safely be shared. As Ted Spence suggests, you should instead create connections only as you need them (and .Dispose() them when you're done with them). .NET has a built in connection pooling mechanism that does a very good job of making sure connections are reused when possible, but holding onto connections any longer than is absolutely necessary can interfere with its ability to do that.
try
dbtool tool = e.result as dbtool;
If you have a variable in dbTool that that gets set to true or false when the query completes then you should be able to call
tool.variable = true/false
Thank you everyone for your input.
I was able to come up with a solution. After coming across Working With The WPF Dispatcher. I determined that you can obtain the UI thread's Dispatcher object:
//...
dbTool = new DBTool();
// Initialize the connection string
// Disable some UI
Thread thread = new Thread(new ThreadStart(
delegate()
{
dbTool.connectToDB();
UIControl.Dispatcher.BeginInvoke(
new Action(
update
));
}
));
thread.Start();
//.....
void update()
{
if (dbTool.validString) // If the connection string was valid
{
// Re-enable controls
}
else // Invalid connection string
{
// Keep controls disabled if no connection could be created
}
}
This indeed will test the connection string on a different thread, leaving the rest of the application responsive.

Categories