Situation
We're using the following code to accept incoming HTTP requests.
var localEndPoint = new IPEndPoint(IPAddress.Any, Port);
var serverSocket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
serverSocket.Bind(localEndPoint);
serverSocket.Listen(backlog: 25);
while (true)
{
using (var clientSocket = serverSocket.Accept())
{
if (clientSocket.Available > 0)
{
var builder = new StringBuilder();
while (clientSocket.Available > 0)
{
var currentBytes = new byte[clientSocket.Available];
var bytesReceived = clientSocket.Receive(currentBytes);
var currentBytesString =
new string(Encoding.UTF8.GetChars(currentBytes));
builder.Append(currentBytesString);
}
}
}
}
Problem
Sometimes clientSocket.Available is zero even though the connection has data. The solution we implemented is to wait after accepting the connection before we check whether data is available. We do it like this:
var start = DateTime.Now;
var duration = new TimeSpan(0);
while (clientSocket.Available <= 0 || duration.Milliseconds < 1000)
{
duration = DateTime.Now - start;
Thread.Sleep(100);
}
Question
After accepting a connection, how long we we need to wait before the connection's data will be available in the socket?
Working Solution
Thank you to szym for the inspiration for this approach. It is working for now.
while (true)
{
using (var clientSocket = serverSocket.Accept())
{
var builder = new StringBuilder();
do
{
var currentBytes = new byte[50];
var bytesReceived = clientSocket.Receive(currentBytes);
var currentBytesString =
new string(Encoding.UTF8.GetChars(currentBytes));
builder.Append(currentBytesString);
}
while (clientSocket.Available > 0);
}
}
Generally, you might need to wait a while (think crappy networks with huge round-trip times), the default timeout on some platforms is 20 seconds!
However, the approach of checking
Availablein a sleepy-loop is polling and is a waste of CPU. You should either block onReceivewhich will just wait for data to arrive (perhaps spawn a thread if you need to handle multiple connections), or use a non-blocking approach.To quote the documentation (emphasis mine):