I have specified the ReceiveTimout as 40 ms. But it takes more than 500ms for the receive to timeout. I am using a Stopwatch to compute the timetaken.
The code is shown below.
Socket TCPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
TCPSocket.ReceiveTimeout = 40;
try
{
TCPSocket.Receive(Buffer);
} catch(SocketException e) { }
You can synchronously poll on the socket with any timeout you wish. If Poll() returns true, you can be certain that you can make a call to Receive() that won't block.
Socket s;
// ...
// Poll the socket for reception with a 10 ms timeout.
if (s.Poll(10000, SelectMode.SelectRead))
{
s.Receive(); // This call will not block
}
else
{
// Timed out
}
I recommend you read Stevens' UNIX Network Programming chapters 6 and 16 for more in-depth information on non-blocking socket usage. Even though the book has UNIX in its name, the overall sockets architecture is essentially the same in UNIX and Windows (and .net)
You cannot use timeout values which are less than 500ms.
See here for SendTimeout: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.sendtimeout
Even though MSDN doesn't state the same requirement for the ReceiveTimeout, my experience shows that this restriction is still there.
You can also read more about this on several SO posts:
Setting socket send/receive timeout to less than 500ms in .NET
WinSock recv() timeout: setsockopt()-set value + half a second?
I found this one:
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect( sIP, iPort, null, null );
bool success = result.AsyncWaitHandle.WaitOne( 40, true );
if ( !success )
{
socket.Close();
throw new ApplicationException("Failed to connect server.");
}
Related
I have a socket that serves a single request-response purpose.
I set it up on port XXX let it wait for a connection, read the data and reply with some data.
I would like to open a new socket on the same port. As soon as the response was sent.
That is handled externally (there is a manager that is checking the state of the thread and if it was used it disposes it and creates a new one.
The problem is that it gets blocked on
_socket = _socket.Accept();
and when a new client tries to connect it never leaves this line. (And client gets no reply).
The socket is running in
new Thread(Run);
and here is my Run method:
private void Run()
{
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, Port);
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
_socket = _socket.Accept();
var data = string.Empty;
while (true)
{
var bytes = new byte[1024];
var bytesRec = _socket.Receive(bytes);
data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>", StringComparison.Ordinal) <= -1) continue;
var dataWithoutEof = data.Substring(0, data.IndexOf("<EOF>", StringComparison.Ordinal));
//TODO: do smt with the data
break;
}
var byteData = Encoding.UTF8.GetBytes("testResponse" + "<EOF>");
_socket.Send(byteData);
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
I suppose that I am not closing the existing socket correctly.
You code is wrong you should not expect this method to exit because you want your server up and running the whole time. I am assuming here you call run several times. Don't do that.
The code becomes then something like this :
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
while (true)
{
var _servicingsocket = _socket.Accept();
....
_servicingsocket.close();
}
accept is a blocking call. That waits for a new connection.
_socket is a listening socket and must be kept during the lifetime of the server.
A TCP connection is based on the notion of a socket pair.
When the server starts you have a single socket that listens on port 100.
Suppose a connection is established, then accept returns what is called a servicing socket that is basically a clone from the listening socket. This means that it is also using source port 100, but because it is a servicing socket it belongs to a socket pair that identifies the connection. A socket pair is the combination of 2 sockets, your own socket and the peer. When a data comes in, TCP will iterate through the socket pairs to find the right socket.
An additional advantage of doing it this way is that you allow other connection attempts to queue up on the listening socket while you are processing the first request. Your _socket is overwritten with the servicing socket and you are then assuming that the listening socket is going to be garbage collected. I am not sure if this is going to happen because I haven't tried it like you are doing it in your code because it is a bad idea in the first place because it implements idisposable. (https://msdn.microsoft.com/en-us/library/system.net.sockets.socket%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) If you really want to close the server you have to make sure to close both the servicing socket and the listening socket to make the code clean.
I have a .NET Socket that listens to all TCP requests on the computer, and aggregates them into HTTP requests (where possible).
I have the following problem -
When I access a site (for example - stackoverflow.com) I see in WireShark that there are X (lets say - 12) TCP packets received from the site's host.
But in my code the Socket just stops receiving the messages before the end (after 10 messages)
I have no idea how to fix this, I hope it's something that is limiting the socket in his definition
Here is my code:
public void StartCapturing()
{
try
{
_chosenOutgoingAddress = UserChoosesIpCtrl();
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw,
ProtocolType.IP);
_socket.Bind(new IPEndPoint(_chosenOutgoingAddress, 0));
_socket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.HeaderIncluded, true);
_socket.IOControl(IOControlCode.ReceiveAll, _bIn, _bOut);
thrStartCapturing = new Thread(StartReceiving);
thrStartCapturing.Name = "Capture Thread";
thrStartCapturing.Start();
}
catch (Exception ex)
{
//TODO: general exception handler
throw ex;
}
}
The StartCapturing method will initiate the Socket and start the receiving thread with the StartReceiving method (as below0
private void StartReceiving()
{
while (!_stopCapturing)
{
int size = _socket.ReceiveBufferSize;
int bytesReceived = _socket.Receive(_bBuffer,
0,
_bBuffer.Length,
SocketFlags.None);
if (bytesReceived > 0)
{
_decPackagesReceived++;
ConvertReceivedData(_bBuffer, bytesReceived);
}
Array.Clear(_bBuffer, 0, _bBuffer.Length);
}
}
What am I doing wrong?
Ok, I figured it out, so I'm posting here for anyone else who might need it in the future
The .NET Socket class has a property ReceiveBufferSize which determines what is the buffer that the Socket will allow.
My problem was that my code wasn't ASync, or fast enough to clean this buffer, so that the last TCP packets had no more buffer and were ignored.
Increasing the ReceiveBufferSize or make my code ASync (probably better :-)) will fix this.
I am working on a client server application, Windows Server and Linux Client. I was testing my server with multiple concurrent clients. I tried just 20 concurrent connections from client, and i noticed that some requests were not processed despite all 20 requests were the same. They went into the queue and for some reason when their turn comes client was shutdown (Client connect timeout is 5 sec).
Then I added a Thread.Sleep(1000), to check if it is really asynchronous but then i realized it does not process other request until timeout. Despite the fact
It is asynchronous
ManualResetEvent was set before going to sleep.
Now I am wondering what Am I missing here, as this happens with concurrent connections mostly?
public static void StartServer(IPAddress ipAddr, int port)
{
//IPEndPoint serverEndPoint = new IPEndPoint(ipAddr, port);
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, port);
Socket clientListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clientListener.Bind(serverEndPoint);
clientListener.Listen(500);
Console.WriteLine("-- Server Listening: {0}:{1}",ipAddr,port);
while (true)
{
resetEvent.Reset();
Console.WriteLine("|| Waiting for connection");
clientListener.BeginAccept(new AsyncCallback(AcceptConnection), clientListener);
resetEvent.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public static void AcceptConnection(IAsyncResult ar)
{
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Signal the main thread to continue.
resetEvent.Set();
// Create the state object.
JSStateObject state = new JSStateObject();
state.workSocket = handler;
if (handler.Connected)
{
Console.WriteLine("** Connected to: {0}", handler.RemoteEndPoint.ToString());
state.workingDirectory = JSUtilityClass.CreatetTemporaryDirectry();
try
{
Thread.Sleep(1000);
Receive(state);
}
catch (Exception e)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.WriteLine(e.Message);
}
}
}
I created a test that sends 100 connection attempts and found a few things slowing it down.
Why is it so slow?
I put a breakpoint in AcceptConnection to look at the callstack, this is it
ConsoleApplication1.exe!ConsoleApplication1.Program.AcceptConnection(System.IAsyncResult ar) Line 62 C#
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) + 0x69 bytes
System.dll!System.Net.ContextAwareResult.CaptureOrComplete(ref System.Threading.ExecutionContext cachedContext, bool returnContext) + 0xab bytes
System.dll!System.Net.ContextAwareResult.FinishPostingAsyncOp(ref System.Net.CallbackClosure closure) + 0x3c bytes
System.dll!System.Net.Sockets.Socket.BeginAccept(System.AsyncCallback callback, object state) + 0xe3 bytes
ConsoleApplication1.exe!ConsoleApplication1.Program.StartServer(System.Net.IPAddress ipAddr, int port) Line 48 + 0x32 bytes C#
So the callback AcceptConnection is running from the same thread that BeginAccept was called from. I had a look at FinishPostingAsyncOp with reflector and it's using the async pattern where if there is already a socket operation in the queue waiting to be processed, it'll do so on the current thread, otherwise if there isn't anything pending, it'll process in a different thread later on, e.g.
SocketAsyncEventArgs sae = new SocketAsyncEventArgs();
sae.Completed += new EventHandler<SocketAsyncEventArgs>(SocketOperation_Completed);
if (!clientListener.AcceptAsync(sae))
AcceptConnection(clientListener, sae); // operation completed synchronously, process the result
else
// operation will complete on a IO completion port (different thread) which we'll handle in the Completed event
So as you observed the program is effectively completely synchronous in this scenario, and with the 1 second Thread.Sleep it's going to take at least 100 seconds to accept all the connections, by which time most of them will timeout.
The solution
Even though BeginAccept method summary says
Begins an asynchronous operation to accept an incoming connection
attempt.
It turns out there is more to the story
From MSDN http://msdn.microsoft.com/en-AU/library/system.net.sockets.socket.beginaccept.aspx
BeginAccept(Int32, AsyncCallback, Object)
Begins an asynchronous operation to accept an
incoming connection attempt and receives the first block of data sent
by the client application.
So it's performing a read operation with a short timeout before firing the callback. You can disable this by specifying the receiveSize of 0. Change
clientListener.BeginAccept(new AsyncCallback(AcceptConnection), clientListener);
to
clientListener.BeginAccept(0, new AsyncCallback(AcceptConnection), clientListener);
That speeds it up, and if we remove the Thread.Sleep(1000) from AcceptConnection then all the connections are accepted really fast.
If you leave the Thread.Sleep(1000) in there to simulate work load or just for testing then you may want to prepare the server to handle such a load by doing
int minWorkerThreads = 0;
int minCompletionPortThreads = 0;
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
ThreadPool.SetMinThreads(minWorkerThreads, 100);
Where 100 is the amount of threads you want readily available to handle socket operations.
Just one other thing, it's a matter of personal preference but just so you know you might like to call BeginAccept from within AcceptConnection which removes the need for that while loop.
i.e. change this
while (true)
{
resetEvent.Reset();
Console.WriteLine("|| Waiting for connection");
clientListener.BeginAccept(new AsyncCallback(AcceptConnection), clientListener);
resetEvent.WaitOne();
}
to this
Console.WriteLine("|| Waiting for connection");
clientListener.BeginAccept(new AsyncCallback(AcceptConnection), clientListener);
and put another BeginAccept in AcceptConnection
public static void AcceptConnection(IAsyncResult ar)
{
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
// start another listening operation
listener.BeginAccept(new AsyncCallback(AcceptConnection), listener);
... the rest of the method
}
I got a strange problem, I never actually expirienced this before, here is the code of the server (client is firefox in this case), the way I create it:
_Socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
_Socket.Bind( new IPEndPoint( Settings.IP, Settings.Port ) );
_Socket.Listen( 1000 );
_Socket.Blocking = false;
the way i accept connection:
while( _IsWorking )
{
if( listener.Socket.Poll( -1, SelectMode.SelectRead ) )
{
Socket clientSocket = listener.Socket.Accept();
clientSocket.Blocking = false;
clientSocket.SetSocketOption( SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true );
}
}
So I'm expecting it hang on listener.Socket.Poll till new connection comes, but after first one comes it hangs on poll forever. I tried to poll it constantly with smaller delay, let's say 10 microseconds, then it never goes in SelectMode.SelectRead. I guess it maybe somehow related on client's socket reuse? Maybe I don't shutdown client socket propertly and client(firefox) decides to use an old socket?
I disconnect client socket this way:
Context.Socket.Shutdown( SocketShutdown.Both ); // context is just a wrapper around socket
Context.Socket.Close();
What may cause that problem?
Have you considered accepting remote clients asynchronously? I answered a similar question recently on TCPListener, but the same pattern can be used for on the Socket Class.
I have never seen this used before to check if a client is available to connect:
listener.Socket.Poll( -1, SelectMode.SelectRead ) )
I had a look inside the Sockets.TCPListener.Pending() method using .NET reflector and they have this instead, maybe you can try it:
public bool Pending()
{
if (!this.m_Active)
{
throw new InvalidOperationException(SR.GetString("net_stopped"));
}
return this.m_ServerSocket.Poll(0, SelectMode.SelectRead);
}
Just bear in mind that according to MSDN the TCPListener.Pending() method is non-blocking so not sure if it helps you 100%?
I am wondering whether I can set a timeout value for UdpClient receive method.
I want to use block mode, but because sometimes udp will lost packet, my program udpClient.receive will hang there forever.
any good ideas how I can manage that?
There is a SendTimeout and a ReceiveTimeout property that you can use in the Socket of the UdpClient.
Here is an example of a 5 second timeout:
var udpClient = new UdpClient();
udpClient.Client.SendTimeout = 5000;
udpClient.Client.ReceiveTimeout = 5000;
...
What Filip is referring to is nested within the socket that UdpClient contains (UdpClient.Client.ReceiveTimeout).
You can also use the async methods to do this, but manually block execution:
var timeToWait = TimeSpan.FromSeconds(10);
var udpClient = new UdpClient( portNumber );
var asyncResult = udpClient.BeginReceive( null, null );
asyncResult.AsyncWaitHandle.WaitOne( timeToWait );
if (asyncResult.IsCompleted)
{
try
{
IPEndPoint remoteEP = null;
byte[] receivedData = udpClient.EndReceive( asyncResult, ref remoteEP );
// EndReceive worked and we have received data and remote endpoint
}
catch (Exception ex)
{
// EndReceive failed and we ended up here
}
}
else
{
// The operation wasn't completed before the timeout and we're off the hook
}
There is a ReceiveTimeout property you can use.
Actually, it appears that UdpClient is broken when it comes to timeouts. I tried to write a server with a thread containing only a Receive which got the data and added it to a queue. I've done this sort of things for years with TCP. The expectation is that the loop blocks at the receive until a message comes in from a requester. However, despite setting the timeout to infinity:
_server.Client.ReceiveTimeout = 0; //block waiting for connections
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);
the socket times out after about 3 minutes.
The only workaround I found was to catch the timeout exception and continue the loop. This hides the Microsoft bug but fails to answer the fundamental question of why this is happening.
you can do like this:
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);