Can someone provide any advice around the following problem. I hope it turns out to be a simple configuration setting, but we shall see.
I have some sample code that illustrates the problem (see later).
When I try to do the following:
1. Create a client/server connection (listening on port 8080)
2. Include an HTTP request/response between client and server
3. Keep the connection open, and drip feed tagged (kind-of-XML) snippets from the server (making sure they aren't too small)
What happens is that the drip fed data from the server is not seen by the client until a significant amount of data has been fed into the socket (>1KByte) (or the socket is closed).
If I change the server listening port to e.g. 9999 and do exactly the same thing again, then the behaviour is what I want - the data is seen by the client without having to wait.
If I feed text data, rather than XML-style tags it seems to work.
If I don't do the HTTP request/response then it seems to work.
If I do smaller XML snippets it seems to work.
We have spent a lot of time playing with socket options (all the ones we could find documented that seemed relevant), and couldn't make it behave as we require.
This behaviour was seen when trying to receive events from a device tunnelled using HTTP - and we found that the events didn't register until about 1.5 minutes after the original event was triggered. We could see the data coming across on the network when the events were happening, and after investigation we concluded that something is going on with the .Net Socket interface (it doesn't happen with unmanaged C socket code). Unfortunately we can't change the way the embedded device is behaving to compensate.
Note the behaviour was seen on both XP and Vista with .Net 3.5 framework installed (and developed using Visual Studio 2008).
If you run the client and server below with port 8080 you will see the problem. Then change the port in the shared code to 9999 you will see the behaviour we want (data received immediately by client).
Here is the client code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using SocketTestSharedData;
namespace sockettest
{
class Program
{
const string address = "127.0.0.1";
static void Main( string[] args )
{
Socket sock1 = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
Console.WriteLine( "Client starting..." );
byte[] response = new byte[ 1536 ];
System.Threading.Thread.Sleep( 5000 );
sock1.Connect( address, SharedData.port );
sock1.Send( ASCIIEncoding.ASCII.GetBytes( SharedData.message1 ) );
int length = sock1.Receive( response );
Console.WriteLine( ASCIIEncoding.ASCII.GetString( response ).ToCharArray(), 0, length );
length = sock1.Receive( response );
Console.Write( ASCIIEncoding.ASCII.GetString( response ).ToCharArray(), 0, length );
if ( length > SharedData.response2.Length )
{
Console.WriteLine( "\n\nWARNING: Not getting data through as expected..." );
}
else
{
length = sock1.Receive( response );
Console.Write( ASCIIEncoding.ASCII.GetString( response ).ToCharArray(), 0, length );
}
Console.WriteLine( "\nClient closing" );
sock1.Close();
System.Threading.Thread.Sleep( 2000 );
}
}
}
Here is the server code (run in a separate process or thread from the client):
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using SocketTestSharedData;
namespace sockserver
{
class Program
{
static void Main( string[] args )
{
//
// Create listening socket
//
Socket sock = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
IPEndPoint ep = new IPEndPoint(IPAddress.Any, SharedData.port);
byte[] command = new byte[ 1536 ];
Console.WriteLine( "Server starting..." );
sock.Bind( ep );
sock.Listen( 10 );
Socket conn1 = sock.Accept();
int length = conn1.Receive( command );
Console.Write( ASCIIEncoding.ASCII.GetString( command ).ToCharArray(), 0, length );
conn1.Send( ASCIIEncoding.ASCII.GetBytes( SharedData.response1 ) );
System.Threading.Thread.Sleep( 2000 );
Console.WriteLine( "Server sending..." );
conn1.Send( ASCIIEncoding.ASCII.GetBytes( SharedData.response2 ), SharedData.response2.Length, 0 );
System.Threading.Thread.Sleep( 2000 );
Console.WriteLine( "Server sending..." );
conn1.Send( ASCIIEncoding.ASCII.GetBytes( SharedData.response3 ), SharedData.response3.Length, 0 );
System.Threading.Thread.Sleep( 5000 );
Console.WriteLine( "Server closing" );
conn1.Close();
sock.Close();
System.Threading.Thread.Sleep( 2000 );
}
}
}
Here is the shared code:
using System;
using System.Collections.Generic;
using System.Text;
namespace SocketTestSharedData
{
class SharedData
{
public const string message1 = "GET /something.html HTTP/1.1\r\n\r\n";
public const string response1 = "HTTP/1.1 200 OK\r\n\r\n";
public const string response2 = "<reply><indent><indent2>Hello</indent2></indent><indent>World</indent><indent><indent2>!</indent2></indent></reply>";
public const string response3 = "<reply><indent><indent2>Blah</indent2></indent><indent>Blah</indent></reply>";
//public const int port = 9999;
public const int port = 8080;
}
}
Many thanks for getting this far!