I am trying to establish a connection through Sockets to send data (for testing purposes to the local IP address, meaning the computer is sending data to "itself").
Previously, everything worked perfectly fine for weeks throughout the development, meaning the connection could be established, the data could be sent and received and the connection could finally be closed, but a few days later, also after restarting my router, I am getting a SocketException (98) when trying to bind the "listener" Socket to an end point with IPAddress.Any (0.0.0.0) with the message: Address already in use.
The source code has not changed in between. The Socket is supposed to accept any connection from any IP-Address, as it is the "listener" Socket for receiving data.
I am using .NET 6.0.301.
This is a simplified version of the relevant source code:
// In the constructor of the base-class:
IpEndPoint = new IPEndPoint(IPAddress.Any, Port); // Random unused port that also hasn't changed
// ...
// Gets called in the constructor of the derived class
private async Task ReceiveDataAsync()
{
using Socket listener = new(IpEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
try
{
listener.Bind(IpEndPoint); // Fails here!!!
listener.Listen(100);
}
catch(Exception e)
{
Console.WriteLine(e);
throw;
}
while(true)
{
using Socket handler = await listener.AcceptAsync();
// Receive data...
}
}
This method is called only once and the exception throws at the very first cycle of the loop. It is called, of course, long before the attempt to establish a connection to this IP.
It might also be important noting that I didn't close the connection after receiving the data with the Shutdown, DisconnectAsync and Close methods, but this has always been done on the client side after the data had been sent.
And here is the exception:
System.Net.Sockets.SocketException (98): Address already in use
at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at ....ReceiveDataAsync() ...
EDIT:
This is the output of netstat -ntpl | grep 0.0.0.0 while my IDE, JetBrains Rider is running with the relevant project being opened (but it isn't executing):
tcp 0 0 0.0.0.0:31415 0.0.0.0:* LISTEN
10064/dotnet
tcp 0 0 127.0.0.1:42103 0.0.0.0:* LISTEN
9560/Rider.Backend
tcp 0 0 127.0.0.1:33747 0.0.0.0:* LISTEN
9560/Rider.Backend
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
-
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
-
Killing the process, which occupies the port, doesn't have much of an effect, as a new process gets created when I launch the application again.
A Bind on a fixed endpoint inside a while (true) is hugely suspicious. You only need to bind once - a single listener socket can accept any number of client connections. Refactor the code so you only bind and listen once, and then just have the accept in the while loop.
If it can't bind even the first time, then that suggests a rogue process is holding the port, or possibly a firewall problem. But my money would be on a rogue process. If you can't find it, try rebooting - if that fixes it: it was a rogue process (probably your own program started from a debugger, or similar).
Related
I am trying to contact to server with C# TcpClient for lots of time. For example, I connect to server for 5s, disconnect then try connect to server in 10s, and repeat...
But eventhogh I set LingerOption and ResueAddress Option as true, ExtendedSocketExcption came out when I reconnect to server.
Here is my code. (.Net5, Windows 10)
TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 50010));
TCPSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
LingerOption lo = new LingerOption(true, 0);
TCPSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
TCPSocket.Connect(new IPEndPoint("10.10.0.50", 50010));
TCPSocket.ReceiveTimeout = 5000;
//Do somthing
TCPSocket.Client.Shutdown(SocketShutdown.Both);
TCPSocket.Close();
Thread.Sleep(5000);
TCPSocket.Connect(new IPEndPoint(SRE3021IP, SRE3021TCPPort)); //ExtendedSocketExeption
And I check on cmd with command netstat -ano | findstr 50010 while thread was sleeping.
TCP 10.10.0.100:50010 10.10.0.50:50010 TIME_WAIT 0
The TIME_WAIT state remained about 30~1 min then It disappeared...
I don't know why linger option was not applied.
Setting a LingerOption doesn't stop a socket from closing. It delays the close() to allow any unsent data in the buffer to be sent. This allows an application to move on to the next phase with a slow network. The socket will still close.
ReuseAddress has nothing to do with reusing an existing socket (believe it or not), it allows a Listening Socket to bind to an existing listening port. This is a very bespoke behaviour and requires other process interops to have two different applications listening on the same port. This option has no useful meaning on an outbound socket connection.
Your problem stems from the fact you're setting a source bind with this line:
TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 50010 ));
If you want to set a source port you have no option but to wait for the OS to clean out the socket from the connection list which means waiting for the TIME_WAIT to expire.
If you don't want to set a source port, (and these days their are very few reasons to actually set a source port) but still want to select a specific source IP address interface then you can use:
TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 0));
If you want Windows to just choose the most appropriate outgoing interface, (and port), then use:
TCPSocket = new TcpClient();
I connected to PCs with a cable in an attempt to simulate server\client. Server starts listening at specific EndPoint and sometimes later a client connects. All went well and I settled on maximum speed of about 24 Mbps for one connection (port).
So now I reversed the roles and can't get connection Socket.BeginConnect(ServerEndPoint, new AsyncCallback(OnConnectCallback), _ClientSocket) times out and sets localEndpoint to 0.0.0.0
Here is the code for client:
public void ConnectToServer(IPAddress iPAddress, int Port)
{
connected.Reset();
IPEndPoint ServerEndPoint = new IPEndPoint(iPAddress, Port);
try
{
_ClientSocket = new Socket(iPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_ClientSocket.BeginConnect(ServerEndPoint, new AsyncCallback(OnConnectCallback), _ClientSocket);
connected.WaitOne();
// Here I would like to start async receiving but there's no connection
}
catch (SocketException)
{
// TODO:
}
}
private void OnConnectCallback(IAsyncResult result)
{
try
{
Socket client_StateSocket = (Socket)result.AsyncState;
client_StateSocket.EndConnect(result);
/// Here I get 0.0.0.0
connected.Set();
}
catch (SocketException)
{
// TODO:
}
}
The server is bascialy from MSDN example. It starts listening for incoming connections, goes in perpetual while cycle and sits waiting for Socket.BeginAccept to trigger (but it never does).
I suspected firewall, but the settings look the same on both PCs and works fine in reversed way, so what might be the problem?
When you do development of a Server/Client architecture, it is usually enough to have both run on the same machine and let them talk via the Loopback IP adress. As a general rule the networking code does not care if the other end is on the same computer, the same switch - or the Voyager 2 probe (well, they do care a little as the Latency is quite high).
If you are having issues in deployment/testing, then with 99% propability you are dealing with a Networking problem, not a programming one. Sometimes there will be some required changes (like exposing the option to set proxy settings). But debugging will be a Networking operation first.
My first guesses are towards firewalls (including the one built into Windows). And then things that work similar to a firewall, like NAT layers.
I've got a little problem with the .Net Sockets in C#.
I programmed a client and a server working with TCP.
As the client is opened it sends a handshake to the server. The server answers with it's state (clientexists, clientaccepted,...). After that the application sends a getdata-request, abandons the connection and listens for the server's 'response'. Now, the server builds a connection to the client and sends all the data the client needs.
The code and everything else works, but the problem:
On our company testserver it works fine, on the live server only the handshake works. After it the client doesn't receive any more data. Serverapplication is the same on both servers.
I thought the problem was caused by some firewall (server wants to build a tcp connection to the client -> not good), but the system administrator said there is no firewall that could block that.
Now I'm searching for a ('cheap') solution that doesn't take too much time and changes in code. If anyone knows how to theoretically solve that, that would be great.
BTW: I am not allowed to do anything on the live server other than run the serverapplication. I don't have the possibility to debug on this server.
I can't publish all of my code, but if you need to see specific parts of it, ask for it please.
---EDIT---
Client-Server communication
1) Client startup
Client send handshake (new tcp connection)
2) Server validates handshake and saves IP
Server responds with it's client state (same tcp connection)
3) Client acknowledges this response and abandons this connection
Client sends getdata-request (new tcp connection)
Client abandons this tcp connection, too
4) Server receives getdata-request and collects the needed data in the main database
Server sends all the collected data to the client (multiple tcp connections)
5) Client receives all data and displays it in it's GUI (multiple tcp connections and the order of the data is kept by working with AutoResetEvents and Counts of sockets to send)
This is the main part my code does. It's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too.
Another thing i forgot to mention is that the solution uses two Ports '16777' and '16778'. One to receive/listen and one to send.
My code is based on the MSDN example of the asynchronous server and client.
Sending a handshake (and getdata-request)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
Server listener
public void StartListening()
{
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(System.Int32.MaxValue);
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)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
Socket send
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
Socket send all data part (answer to getdata-request | socToHandle should be the socket of the previous connection of the getdata-request)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
Looking through my old code I have one idea =>
Could I send everything over the same connection by changing:
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
(which creates a new connection) to something that uses the same connection?
If that would work, how can I do that?
And would the listener part of the client still receive single packets?
Servers and their environment are configured to handle incoming requests properly. Clients are usually behind a router, which by default make them unable to receive incoming connections from outside their network (a good thing).
To enable incoming connections, you could configure your router to forward all requests for a certain port number to your machine. No one else on your network would be able to run the client then, though.
This is why in a typical multiple clients-single server environment, the client makes all the connections, and only the server requires any changes to the network landscape.
I don't know why you chose to connect to the clients from the server side, but I would strongly advise against this - any cheap solution that uses this mechanism may turn out to be very expensive in the end.
I have a "start" and "stop" button. When clicking the start button, a new socket is created and a connection is made. When clicking the stop button the socket is shutdown, disconnected, closed and disposed to make sure it is completely gone.
At least, that's what I thought: when clicking start after stopping the connection, a new socket is made etc. but as soon as I send data, the data is sent x amount of times I had created a socket (thus, x amount of times I had clicked the start button).
This is the code for the start:
soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Socket soc; is declared at class-level
System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse(IP);
System.Net.IPEndPoint remoteEP = new IPEndPoint(ipAdd, port);
try
{
soc.Connect(remoteEP);
soc.Send(jsonSettings);
}
catch (SocketException e)
{
MessageBox.Show("Could not connect to socket");
}
And this is the stop code:
if (soc != null)
{
soc.Shutdown(SocketShutdown.Both);
soc.Disconnect(false);
soc.Close();
soc.Dispose();
}
This is used within a VSTO PowerPoint add-in application if this could cause any additional specialties, when the connection is made I'm sending string data to a Python server listening to this port. Each time a connection is closed, the Python server will get out of it's listen-for-data loop and get back in it's waiting for connection state (for the multiple start/stop connections).
Code for sending data:
// this is called each time the user goes to another slide in the PowerPoint presentation
byte[] byData = System.Text.Encoding.ASCII.GetBytes(stringValue);
soc.Send(byData);
Can anyone point out what I'm doing wrong why the socket connections somehow keep on living and sending data even though I disconnected and closed them?
The observed behavior is the whole point and desired outcome from clean shutdown. From the MSDN page for Socket.Shutdown():
When using a connection-oriented Socket, always call the Shutdown method before closing the Socket. This ensures that all data is sent and received on the connected socket before it is closed.
The call to Shutdown() prevents your application from queuing additional outgoing data, it does not stop the network stack from sending data already buffered.
Since you are using a stream socket, how about declaring a network stream for your socket like this:
NetworkStream stream = new NetworkStream(soc);
Then flushing this after each send (and before closing the socket):
stream.Flush();
Also ensure you turn off Nagle's algorithm when you create the socket - it will prevent batching up items on the socket:
soc.NoDelay = true;
I'm trying to reuse a socket in an asynchronous HTTP client, but I'm not able to connect to the host the second time around. I basically treat my asynchronous HTTP client as a state machine with the following states:
Available: the socket is available for use
Connecting: the socket is connecting to the endpoint
Sending: the socket is sending data to the endpoint
Receiving: the socket is receiving data from the endpoint
Failed: there was a socket failure
Clean Up: cleaning up the socket state
In the connecting state I call BeginConnect:
private void BeginConnect()
{
lock (_sync) // re-entrant lock
{
IPAddress[] addersses = Dns.GetHostEntry(_asyncTask.Host).AddressList;
// Connect to any available address
IAsyncResult result = _reusableSocket.BeginConnect(addersses, _asyncTask.Port, new AsyncCallback(ConnectCallback), null);
}
}
The callback method changes the state to Sending once a successful connection has been established:
private void ConnectCallback(IAsyncResult result)
{
lock (_sync) // re-entrant lock
{
try
{
_reusableSocket.EndConnect(result);
ChangeState(EClientState.Sending);
}
catch (SocketException e)
{
Console.WriteLine("Can't connect to: " + _asyncTask.Host);
Console.WriteLine("SocketException: {0} Error Code: {1}", e.Message, e.NativeErrorCode);
ThreadPool.QueueUserWorkItem(o =>
{
// An attempt was made to get the page so perform a callback
ChangeState(EClientState.Failed);
});
}
}
}
In the cleanup I Shutdown the socket and Disconnect with a reuse flag:
private void CleanUp()
{
lock (_sync) // re-entrant lock
{
// Perform cleanup
if (_reusableSocket.Connected)
{
_reusableSocket.Shutdown(SocketShutdown.Both);
_reusableSocket.Disconnect(true);
}
ChangeState(EClientState.Available);
}
}
Subsequent calls to BeginConnect result in a timeout and an exception:
SocketException: A connection attempt
failed because the connected party did
not properly respond after a period of
time, or established connection failed
because connected host has failed to
respond XX.XXX.XX.XX:80
Error Code: 10060
Here is the state trace:
Initializing...
Change State: Connecting
Change State: Sending
Change State: Receiving
Change State: CleanUp
Callback: Received data from client 0 // <--- Received the first data
Change State: Available
Change State: Connecting // <--- Timeout when I try to reuse the socket to connect to a different endpoint
What do I have to do to be able to reuse the socket to connect to a different host?
Note: I have not tried to re-connect to the same host, but I assume the same thing happens (i.e. fails to connect).
Update
I found the following note in the documentation of BeginConnect:
If this socket has previously been disconnected, then BeginConnect must be called on a thread that will not exit until the operation is complete. This is a limitation of the underlying provider. Also the EndPoint that is used must be different.
I'm starting to wonder if my issue has something to do with that... I am connecting to a different EndPoint, but what do they mean that the thread from which we call BeginConnect must not exit until the operation is complete?
Update 2.0:
I asked a related question and I tried using the "Async family" calls instead of the "Begin family" calls, but I get the same problem!!!
I commented on this question: what is benefit from socket reuse in C# about socket reuse using Disconnect(true)/DisconnectEx() and this may help you.
Personally I think it's an optimisation too far in client code.
Re update 1 to your question; no, you'd get an AbortedOperation exception if that were the case (see here: VB.NET 3.5 SocketException on deployment but not on development machine) and the docs are wrong if you're running on Vista or later as it doesn't enforce the "thread must exist until after overlapped I/O completes" rule that previous operating systems enforce.
As I've already said in the reply to the linked question; there's very little point in using this functionality for outbound connection establishment. It's likely that it was originally added to the Winsock API to support socket reuse for AcceptEx() on inbound connections, where, on a very busy web server that was using TransmitFile() to send files to clients (which is where disconnect for reused seems to have originated). The docs state that it doesn't play well with TIME_WAIT and so using it for connections where you initiate the active close (and thus put the socket into TIME_WAIT, see here) doesn't really make sense.
Can you explain why you think this micro optimisation is actually necessary in your case?
have you checked the MaxConnections Setting?
http://msdn.microsoft.com/de-de/library/system.servicemodel.nettcpbinding.maxconnections.aspx