Description
Describe the bug
In out WCF application we use void Test(int i)
method with IsOneWay=True
attribute.
The method is called every second. Server processing is negligible (~1 ms).
If we specify client timeouts ~5..7 sec, it will throw timeout exception on ~5..7th call.
Same code under .Net Framework works fine.
The exception thrown:
System.ServiceModel.CommunicationException: The socket was aborted because an asynchronous receive from the socket did not complete within the allotted timeout of 00:00:05.8140000. The time allotted to this operation may have been a portion of a longer timeout.
---> System.IO.IOException: The write operation failed, see inner exception.
---> System.ServiceModel.CommunicationException: The socket was aborted because an asynchronous receive from the socket did not complete within the allotted timeout of 00:00:05.8140000. The time allotted to this operation may have been a portion of a longer timeout.
---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError& errorCode)
at System.ServiceModel.Channels.SocketConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.SocketConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
at System.ServiceModel.Channels.BufferedConnection.WriteNow(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, BufferManager bufferManager)
at System.ServiceModel.Channels.BufferedConnection.WriteNow(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
at System.ServiceModel.Channels.BufferedConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
at System.ServiceModel.Channels.ConnectionStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Security.NegotiateStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.NegotiateStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
--- End of inner exception stack trace ---
at System.Net.Security.NegotiateStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.NegotiateStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.ServiceModel.Channels.StreamConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.StreamConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
at System.ServiceModel.Channels.StreamConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout, BufferManager
bufferManager)
at System.ServiceModel.Channels.FramingDuplexSessionChannel.OnSendCore(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.TransportDuplexSessionChannel.OnSend(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.OutputChannel.Send(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.DuplexChannelBinder.Send(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, Ti
meSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)
--- End of stack trace from previous location where exception was thrown ---
at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)
....
To Reproduce
Simple app to reproduce issue:
using System;
namespace TestInterface
{
using System.ServiceModel;
public static class TestConst
{
public const string DEF_URL = "net.tcp://localhost:8080/ITestService";
}
[ServiceContract]
public interface ITestService
{
[OperationContract( IsOneWay = true )]
void Test( int I );
}
}
namespace TestClient
{
using System.ServiceModel;
using System.Threading;
using TestInterface;
static class Client
{
public static void ClientLoop( string ServerUrl = TestConst.DEF_URL )
{
ChannelFactory<ITestService> TestFactory = new ChannelFactory<ITestService>( new NetTcpBinding
{
OpenTimeout = new TimeSpan( 0, 0, 0, 0, 5000 ),
SendTimeout = new TimeSpan( 0, 0, 0, 0, 6000 ),
ReceiveTimeout = new TimeSpan( 0, 0, 0, 0, 7000 ),
CloseTimeout = new TimeSpan( 0, 0, 0, 0, 8000 ),
}, new EndpointAddress( ServerUrl ) );
var TestChannel = TestFactory.CreateChannel();
int ReqNumber = 0;
int GoodCalls = 0;
Console.WriteLine( "Client Start" );
Console.WriteLine( "Press any key to stop..." );
while( true )
{
if( Console.KeyAvailable )
{
return;
}
try
{
TestChannel.Test( ReqNumber );
ReqNumber++;
GoodCalls++;
Console.WriteLine( $"DONE ReqNum:{ReqNumber} [Good: {GoodCalls}]" );
}
catch( Exception Ex )
{
ReqNumber++;
GoodCalls = 0;
Console.Error.WriteLine( $"FAIL ReqNum:{ReqNumber} ERROR:{GoodCalls} {Ex}");
}
finally
{
Thread.Sleep( 1000 );
}
}
}
}
}
#if NETCOREAPP
namespace TestServer
{
using TestInterface;
static class Server
{
public static void ServerLoop( string ServerUrl = TestConst.DEF_URL )
{
Console.Error.WriteLine( "Server is not available under .net core (user .net framework)" );
}
}
}
#else
namespace TestServer
{
using System.ServiceModel;
using TestInterface;
static class Server
{
public static void ServerLoop( string ServerUrl = TestConst.DEF_URL )
{
try
{
ServiceHost Host = new ServiceHost( typeof( TestService ) );
Host.AddServiceEndpoint( typeof( ITestService ), new NetTcpBinding
{
OpenTimeout = new TimeSpan( 0, 0, 0, 0, 5000 ),
SendTimeout = new TimeSpan( 0, 0, 0, 0, 6000 ),
ReceiveTimeout = new TimeSpan( 0, 0, 0, 0, 7000 ),
CloseTimeout = new TimeSpan( 0, 0, 0, 0, 8000 )
}, new Uri( ServerUrl ) );
Host.Open();
Console.WriteLine( "Server start" );
Console.ReadKey();
}
catch( Exception Ex )
{
Console.Error.WriteLine( Ex );
Console.ReadKey();
}
}
}
public class TestService : ITestService
{
public void Test( int i )
{
Console.WriteLine( $"{i}" );
}
}
}
#endif
namespace TestMain
{
using System.Linq;
static class TestMain
{
static void Main( string[] Args )
{
if( Args.Contains( "-server" ) )
{
TestServer.Server.ServerLoop();
}
else
{
TestClient.Client.ClientLoop();
}
}
}
}
Compile provided code under .Net Framework
Check full framework version:
start testapp.exe -server
start testapp.exe
code runs fine (check for ~40 sec), actually it may run forever
Compile provided code under .NetCore
Check netcore client version:
start testapp.exe -server
start testapp.netcore.exe
System will throw exception
Expected behavior
The system should run without exception, producing new line on console very 1 sec.
Screenshots
.Net Framework client and .Net Framework server operation