I want to close a socket so I can reopen one on the same port but I do not have a handle on that socket.
How can I get the socket that is listening on localhost:873 to close it?
Without a kernel driver this is not possible. It is not legal in Windows to grab a socket handle in another process and close it proactively.
Only that process that owns the socket can close it, so all you could try is ending the process that owns the socket.
From the command line you can find the Process ID of the process using a particular socket using the -o option to netstat. For example:
netstat -noa | findstr LISTENING
I don't know how you do this programmatically in .NET though.
You could investigate SO_REUSEADDR.
Related
Background
On Linux or BSD, it is possible to send handles to open files or sockets between unrelated processes with SCM_RIGHTS, and I have this working, such that on process is listening for connections, and then forwards the handles to a process that performs the communication.
Problem
I am unable to figure out how to free the socket handle from the listening process without shutting down the socket.
There are two conflicting descriptions in man close(3):
When all file descriptors associated with an open file description have been closed, the open file description shall be freed.
And
If fildes refers to a socket, close() shall cause the socket to be destroyed.
I originally thought that this means that calling close() will just decrement the reference count for the kernel object that has the socket, such that the last description from man close(3) meant "destroy when the last descriptor is closed".
EDIT: This is how it is supposed to work, and also how it works.
But, when I run tests, it appears that as soon as I call close() on the socket descriptor in the listening process, it will start closing the socket, sending either RST or FIN, depending on what the other process is doing with the socket at the time.
One solution would be to have a callback from the handing process with "you can now close socket nnn", but this would keep a number of socket descriptors open in the listening process and add some overhead as well.
I know I can force the socket to start the shutdown process by calling shutdown() directly from either process, but I want to prevent it.
I assume there exists a simple solution, but I cannot find it.
Question
Is there a way to de-register the socket descriptor from the listening process such that it is no longer in the file descriptor table of the process, but without activating the socket shutdown?
Source code
The SCM_RIGHTS implementation used to send the socket is here (send_fds and native_close):
https://github.com/kenkendk/SockRock/blob/master/src/ScmRightsImplementation.cs
The code that sends the socket and then closes it is here:
https://github.com/kenkendk/ceenhttpd/blob/master/Ceen.Httpd.Cli/Runner/SubProcess/SpawnRemoteInstance.cs#L488-L497
If I comment out line 497 everything works, but obviously get a large file descriptors leak.
The receiving end of SCM_RIGHTS is here:
https://github.com/kenkendk/ceenhttpd/blob/master/Ceen.Httpd.Cli/Runner/SubProcess/SpawnedRunner.cs#L313
tl;dr: The socket is closed when the last reference is closed.
The answer to my question is most likely:
No, there is no way to prevent the socket shutdown, but it is not needed as the socket will not close until the last descriptor has closed.
The answer from Andrew was correct, and got me on track: it makes no sense, others do the same all the time.
In the end, the problem was a timeout in the handler process that closed the socket, but that made it look like the close() call from the listener was the problem.
When I stopped the close() call from the listening process, it started working. This happens because then the timeout correctly closes the handle, but there is still a reference (in the listening process) so the socket stays open.
I'm now working on a tcp socket connection to tcp server running in ESP32.
It works fine for the communication, but I failed to close the connection.
After searching for the solution on close/reset tcpClient, it seems that the proper way to close a tcpClient should be:
tcpClient.GetStream().Close();
tcpCLient.Close();
The example in msdn also use this method.
But unforunately, it cannot really close the connection. As checked in the mcu, the connection has not been closed. And it will not be closed even I close the application later. In this case, the mcu's tcp connection cannot be released, it cannot receive other connections. So, I think this should not be a proper solution to close the tcpClient.
If I did not execute above statement, and close the application directly, it can close the connection successfully. And the mcu's tcp connection is released.
It seems that the there has something been done in application close which can really close the connection.
In some situation, I need to close the connection after some operation, and reconnect it. So, I cannot rely on the application close.
I have tried all the following methods in some different combination, but none of them can successfully release the tcpClient connection:
tcpClient.Close();
tcpClient.Client.Close();
tcpClient.GetStream().Close();
tcpClient.Client.Disconnect(true);
tcpClient.Client.Disconnect(false);
tcpClient.Dispose();
tcpClient.Client.Dispose();
tcpCLient = null;
Maybe it should be done with some of above commands in a proper sequence.
Does anyone know how I cannot close the connection by myself.
Thanks in advance.
After studying the network packet using WireShark, it was found that the problem is due to the delay of sending RST with the code as suggested in MSDN:
tcpClient.GetStream().Close();
tcpCLient.Close();
There has no different even adding
tcpClient.LingerState = new LingerOptions(true, 0);
Because it will send FIN immediately, but not the RST after the Close method, it will be sent around 2 minutes later. Unfortunately, it won't be sent even you close the application after tcpClient close is issued.
If you close the application before closing the tcpClient, it will send the RST immedicately.
So that it can close the connection in server immediately.
After testing different combination of command, it was found that the following code can really close the connection immediately, but there will have another RST around 40 seconds later.
tcpClient.Client.Close();
tcpClient.Close();
Don't call tcpClient.GetStream().Close(); !!! It will cause the delay of RST.
I don't know if there has any impact closing the connection in this way, but this is the only way I can really close the connection immediately.
As you mentioned, this is the correct way to close a TcpClient:
tcpClient.GetStream().Close();
tcpCLient.Close();
Close() will eventually close the connection. Take a look at the documentation for TcpClient.Close()
The Close method marks the instance as disposed and requests that the associated Socket close the TCP connection. Based on the LingerState property, the TCP connection may stay open for some time after the Close method is called when data remains to be sent. There is no notification provided when the underlying connection has completed closing.
You may be able to get the behavior you desire by changing the LingerState property of the TcpClient object.
tcpClient.LingerState = new LingerOptions(true, 0);
I have a C# application that uses D-Link GSM Modem to send/receive SMS messages.
Now for some reason the D-Link USB gets disconnected and reconnected automatically after some time (random). When it re-connects it opens up the D-Link Connection Manager which reserves the COM4.
Now when my application run and tries to send SMS it fails, because it doesn't find any available (already in use my D-Link Manager).
when i tried as at application load if the D-Link Process is there I'm killing it using process.kill(). That kills the application but still the COM4 remains inaccessible.
Is there a way to kill the process and release the COM port also programmatically ?
Killing a process doesn't give it a chance to clean up. It is easy for COM ports to get hung up if clients terminate abnormally.
Try Process.CloseMainWindow. Hopefully, the process will respond by shutting down normally and closing the COM port. You would have to give it some time to shut down, though, for which you could use Process.WaitForExit.
The SerialPort class implements IDisposable for exactly this reason: to clean up unmanaged resources (like the port itself) when the port variable goes out of scope.
using (var serialPort = new SerialPort())
{
// Set the read/write timeouts
serialPort.ReadTimeout = 500;
serialPort.WriteTimeout = 500;
serialPort.Open();
// do something
}
It won't always get cleaned up when you kill the process, but this way, you're giving it a fighting chance.
one should blame poorly designed operating system for not being capable to clean the resources of the process after killing it
I use RabbitMQ.Client (runtime version v2.0.50727, version 2.8.1.0) with C# .NET application.
I create connection like this:
using (IConnection connection = _factory.CreateConnection())
{
using (IModel channel = connection.CreateModel())
{
// code...
}
}
If I close the application properly, it simply closes the channel and connection. But if application is closed incorrectly (e.g. pressing restart button on PC), it is not. I would like to ensure that all unnecessary connections (from previous sessions or even other applications, if by mistake other instance of the application is running somewhere else) are closed before I start my application.
I know I may use heart beats but it is possible that my application requires really much time to start doing anything (many hours of opened connection and not being used). So I think heartbeat is not the best thing.
How can I close all opened connections for RMQ? (Or, even better, all opened connections, with the exception for one given IP)?
Regards!
I encountered the same problem as you. I tried a lot of methods to close those connections.
Those methods, some are works some are only part works. Maybe you can have a try.
Use rabbitmqctl command to delete the queues then use RMQ's management website close the connections. It means current opened queues will expire after 1 second(1000 miliseconds). This way all queues are deleted. Then you can close connections.
Command:
rabbitmqctl set_policy expiry ".*" '{"expires":1000}' --apply-to queues
Queue Time-To-Live policy--> https://www.rabbitmq.com/ttl.html
This method works partly.
After searching, got the idea that reason might be:
Your producer waiting the return ACK back, it won't be destroyed untill you send ACK to acknowledge the job has finished.
Abrupt way. Works. RMQ save connections information in its DB menisa.
Step1: Stop rabbitmq-server first, and kill rabbitmq thread by 'ps aux | grep rabbitmq' to find its pid then kill all rabbitmq thread.
Find RMQ DB mensia location
(1). $> cd /var/lib/rabbitmq/
Step2: rename mensia file to another name to "delete"
(2). $> mv mensia mensia-bak
Step3: restart rabbitmq-server
The third methods works for me now. It can close all open connections.
Sounds like Heartbeats is your best solution. I added heartbeats to my RabbitMQ apps for the same reason (ungraceful shutdowns). It shouldn't matter that there is a long gap of time between messages, heartbeat will just verify that the connection is still open on both sides.
I had the same problem when I open worker in console and than stop it with ctrl+c. After than process is closed but connection is still there and it's visible in admin panel.
One solution is to close connection in RabbitMQ Admin panel
or you can found the process and kill it manual sudo kill -9 pid
or when you open an connection set HEARTBEAT. Read [Dead TCP Connections]
I've created an asynchronous server in C# to go along with my Android application. The server is similar to this: http://msdn.microsoft.com/en-us/library/fx6588te.aspx
It works well and I can have many clients connect and receive data from the server at the same time. One problem that I've found is that in my Android app if you are already connected over Wifi and press the connect button again, the server spawns a new socket. The server should kill the old connection first and then create a new connection. On the Android side I make sure to call close() and even set it to null afterwards. I also send a disconnect control signal to the server so that it can also call close() on the socket. For example, here's how I do it in the server:
if (state.storage.parseJson(content) == JsonStorage.DISCONNECT)
{
Console.WriteLine("Disconnect2!");
state.workSocket.Shutdown(SocketShutdown.Both);
state.workSocket.Close();
return;
}
When I inspect my server process in a program called "CurrPorts" it shows several connections open to my Android device on different ports. I send data to my clients using a Timer object, and I also check to see if the connection is active otherwise I close it. For example, my TimerCallback method:
public void TimeCallBack(object input)
{
StateObject state = (StateObject)input;
if (state.workSocket.Connected)
{
Send(state.workSocket, state.storage.getJson());
}
else
{
Console.WriteLine("Dispose!");
state.timer.Dispose();
state.workSocket.Close();
}
}
I can't think of why my server isn't closing old connections. There should only be as many connections open as devices connected to the server. If this were a threaded blocking server then it would be easy to just close the thread down, but I'm not sure what to do in this case.
edit: so I just refreshed the CurrPorts program after letting it sit for a while and it dropped down to one established connection. Is my solution right and it just takes a while for Windows to actually clear the old socket connections that were created?
Yes, Windows will keep around the information about the socket for a while. You can see this with netstat, closed sockets will show a state of TIME_WAIT after they are closed and even after the application that hosted the socket has terminated.