|
Creating a HTTP Push type service using a single channel Hi,
I've got the following requirements for a WCF service...
* a push type service, ie a server which can send notifications to clients.
* able to be hosted in IIS 6.0 (ie without WAS in vista server, it must be
HTTP).
* uses a single channel to accomplish this - to simplify deployment of the
solution (ie a port should not have to be allocated on the client for the
callback from the server), that means I can't use wsDualHttpBinding with a
callbackchannel.
The Concept -
Return a long running stream of bytes to the client, with notifications
contained within the stream.
The service contract...
[ServiceContract]
public interface ITestNotifier
{
[OperationContract]
Stream GetNotification(string clientID);
}
Which is implemented as...
[ServiceBehavior]
public class TestNotifier : ITestNotifier
{
#region ITestNotifier Members
public Stream GetNotification(string clientID)
{
PumpStream retStream = new PumpStream();
return retStream;
}
#endregion
}
Pumpstream is a custom stream class...
public class PumpStream : Stream
{
int mPosition = 0;
public override bool CanRead { get { return true; }}
public override bool CanSeek { get { return false; }}
public override bool CanWrite { get { return false; }}
public override void Flush() { throw new
NotImplementedException(); }
public override long Length { get { return 2000000; } }
public override long Position { get { throw new
NotImplementedException();} set {throw new NotImplementedException();}}
public override int Read(byte[] buffer, int offset, int count)
{
// Proof of concept, real implementation would have a
EventWaitHandle
// which would be set when ever data becomes available
System.Threading.Thread.Sleep(2000);
for(int i=0; i<count; ++i)
buffer[offset+i] = 0;
mPosition += count;
return count;
}
public override long Seek(long offset, SeekOrigin origin) { throw
new NotImplementedException(); }
public override void SetLength(long value) { throw new
NotImplementedException();}
public override void Write(byte[] buffer, int offset, int
count){throw new NotImplementedException();}
}
The service config...
<basicHttpBinding>
<binding name="FSNotifierBinding" closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="23:59:59" maxBufferSize="256"
maxBufferPoolSize="524288" maxReceivedMessageSize="512"
messageEncoding="Text"
transferMode="Streamed">
<security>
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
The client config...
<basicHttpBinding>
<binding name="FSNotifierEndpoint" closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="23:59:59" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="256" maxBufferPoolSize="524288"
maxReceivedMessageSize="512 "
messageEncoding="Text" textEncoding="utf-8" transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
The problem -
Getting control over the way WCF reads and sends data from the stream.
Ideally I would like it to read a single byte from the stream and then send
it directly to the client.
I've tried altering the maxBytesPerRead, maxReceivedMessageSize and the
maxBufferSize on both the client and the server and none of these settings
seems to affect the number of bytes being read from the stream before a
response is sent to the client.
Does anyone have ideas or alternative suggestions?
TIA
Michael |