I'm writing a local-machine client/server application using an application-hosted WCF service over nettcpbinding with a duplex channel (i.e., peer-to-peer communication). For legacy reasons, this is .NET 3.5.
This code sets up the server:
var netTcpBinding = new NetTcpBinding(SecurityMode.Transport);
netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
netTcpBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
netTcpBinding.ReceiveTimeout = new TimeSpan(0, 0, 14);
netTcpBinding.SendTimeout = new TimeSpan(0, 0, 30);
netTcpBinding.OpenTimeout = new TimeSpan(0, 0, 30);
netTcpBinding.CloseTimeout = new TimeSpan(0, 0, 30);
netTcpBinding.ListenBacklog = 2;
netTcpBinding.MaxConnections = 200;
netTcpBinding.MaxBufferPoolSize = 10 * 1000 * 1000;
netTcpBinding.MaxBufferSize = 10* 1000 * 1000;
netTcpBinding.MaxReceivedMessageSize = 10* 1000 * 1000;
netTcpBinding.PortSharingEnabled = true;
netTcpBinding.ReliableSession.Enabled = true;
netTcpBinding.ReliableSession.Ordered = true;
netTcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(23, 59, 59);
ISmartBrowserClientServiceCallback callback = new SmartBrowserClientServiceCallback();
InstanceContext context = new InstanceContext(callback);
smartBrowserServiceFactory = new DuplexChannelFactory<ClientService.ISmartBrowserClientService>(
context,
netTcpBinding,
new EndpointAddress(uri));
this.channel = this.smartBrowserServiceFactory.CreateChannel();
This code sets up the client:
var netTcpBinding = new NetTcpBinding(SecurityMode.Transport);
netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
netTcpBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
netTcpBinding.ReceiveTimeout = new TimeSpan(23, 59, 59);
netTcpBinding.OpenTimeout = new TimeSpan(0, 0, 15); // timeout seconds are different to help debugging
netTcpBinding.SendTimeout = new TimeSpan(0, 0, 17);
netTcpBinding.ReceiveTimeout = new TimeSpan(0, 0, 19);
netTcpBinding.CloseTimeout = new TimeSpan(0, 0, 21);
netTcpBinding.ListenBacklog = 2;
netTcpBinding.MaxConnections = 100;
netTcpBinding.MaxBufferPoolSize = 10 * 1000 * 1000;
netTcpBinding.MaxBufferSize = 10 * 1000 * 1000;
netTcpBinding.MaxReceivedMessageSize = 10 * 1000 * 1000;
netTcpBinding.PortSharingEnabled = true;
netTcpBinding.ReliableSession.Enabled = true;
netTcpBinding.ReliableSession.Ordered = true;
netTcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(23, 59, 59);
ISmartBrowserClientServiceCallback callback = new SmartBrowserClientServiceCallback(this.smartBrowserClient);
InstanceContext context = new InstanceContext(callback);
this.smartBrowserServiceFactory = new DuplexChannelFactory<ISmartBrowserClientService>(
context,
netTcpBinding,
new EndpointAddress(new Uri(string.Format(CultureInfo.InvariantCulture, "net.tcp://localhost:{0}/Cpy.SmartBrowser.SmartBrowserClientService/", defaultPort.ToString(CultureInfo.InvariantCulture)))));
this.smartBrowserServiceFactory.Faulted += (sender, e) =>
{
this.smartBrowserServiceFactory = null;
};
this.channel = this.smartBrowserServiceFactory.CreateChannel();
Now, when a client calls a service method with some data, that data is well received by the service, which acts upon it, but for some reason there's a TimeoutException on the sender after 17 seconds, the value I picked for the SendTimeout. I find this strange, because all data to send was already sent, instantly, and I see no reason for the system to wait for anything.
This client/server app will be used on a local machine with a single service and a single client, just peer-to-peer communicating. But if I can't get rid of this timeout, I'll have to work around it in a dirty way, which I want to avoid.
What obvious thing am I missing?
Related
I'm trying to activate transport security for a WCF Client-Server application.
It works fine on our test machine, but in the target environment the connection is always reset after what looks to me like a successful handshake:
Wireshark capture
I've tried deactivating the firewall, although the application worked fine without TLS, but it made no difference. I've also tried TLS1.1 and TLS1.0 but that made no difference either.
Here is the source code for the service host:
public void Start()
{
var binding = new NetTcpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
binding.Security.Transport.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
binding.ReliableSession.Enabled = true;
binding.ReliableSession.InactivityTimeout = TimeSpan.FromSeconds(30);
binding.ReceiveTimeout = TimeSpan.FromSeconds(5);
binding.SendTimeout = TimeSpan.FromSeconds(5);
binding.MaxReceivedMessageSize = 64 * 1048576;
binding.ReaderQuotas.MaxArrayLength = 2147483647;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
this.host = new ServiceHost(
this,
new[] { new Uri(string.Format("net.tcp://{0}:{1}", this.hostname, this.port)) }
);
this.host.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
this.host.AddServiceEndpoint(new UdpDiscoveryEndpoint());
this.host.AddServiceEndpoint(typeof(ILvsService), binding, "LvsService");
this.host.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
this.hostname
);
this.host.Open();
}
And here is the client side:
public ServiceClient(string server, ushort port)
{
var binding = new NetTcpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
binding.Security.Transport.SslProtocols = System.Security.Authentication.SslProtocols.Tls12;
binding.MaxReceivedMessageSize = 64 * 1048576;
binding.ReaderQuotas.MaxArrayLength = 2147483647;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
binding.ReceiveTimeout = TimeSpan.FromSeconds(5);
binding.SendTimeout = TimeSpan.FromSeconds(5);
var context = new InstanceContext(this);
this.channelFactory = new DuplexChannelFactory<ILvsService>(
context,
binding,
new EndpointAddress(string.Format("net.tcp://{0}:{1}/LvsService", server, port))
);
}
The server is running as a service on a Windows Server 2016 VM with .NET Framework 4.7.2. The clients are running on Windows 10 machines also with .NET Framework 4.7.2.
I have a C# app calling a Soap client using WCF. The first call to the service succeeds, but any calls thereafter fail.
The code to setup the client is:
public WebserviceHelper(string username, string password, string webserviceURL)
{
var binding = new BasicHttpBinding();
binding.MaxBufferPoolSize = 2147483647;
binding.MaxBufferSize = 2147483647;
binding.MaxReceivedMessageSize = 2147483647;
binding.OpenTimeout = new TimeSpan(0, 1, 0);
binding.ReceiveTimeout = new TimeSpan(0, 1, 0);
binding.SendTimeout = new TimeSpan(0, 1, 0);
var endpoint = new EndpointAddress(webserviceURL);
var channelFactory = new ChannelFactory<EntityAPISoap>(binding, endpoint);
SoapClient = new EntityAPISoapClient(binding, endpoint);
SoapClient.Endpoint.Behaviors.Add(new CustomEndpointBehavior(username, password));
var isAlive = SoapClient.isAlive();
Console.WriteLine(SoapClient.State); //Opened
isAlive = SoapClient.isAlive(); //timeout exception
}
The first call to isAlive returns immediately, the second call times out with this exception:
The request channel timed out while waiting for a reply after
00:01:00. Increase the timeout value passed to the call to Request or
increase the SendTimeout value on the Binding. The time allotted to
this operation may have been a portion of a longer timeout.
I've increased the timeout, but then it just takes longer to respond and anyway the server responds within a second, so 1 minute is more than enough.
I create WCF application that used Azure Cloud Service.
Sometimes client catch TimeoutException About 3 times a day.
Now, Total of client amounts about 100 clients.So The 100 cleint access wcf server at the same time.
The setting is below.How do I optimize? or Do I mistake?
WorkerRols.cs
ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;
var netTcpBinding = new NetTcpBinding();
netTcpBinding.Security.Mode = SecurityMode.Transport;
netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
netTcpBinding.MaxBufferPoolSize = 314572800;
netTcpBinding.MaxReceivedMessageSize = 20971520;
netTcpBinding.MaxBufferSize = 20971520;
netTcpBinding.ListenBacklog = 2147483647;
netTcpBinding.MaxConnections = 2147483647;
netTcpBinding.ReceiveTimeout = new TimeSpan(0, 1, 0);
//binding.SendTimeout = new TimeSpan(0, 3, 0);
//binding.CloseTimeout = new TimeSpan(0, 3, 0);
netTcpBinding.ReliableSession.Enabled = true;
netTcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(0, 1, 0);
ServiceThrottlingBehavior throttle;
throttle = host.Description.Behaviors.Find<ServiceThrottlingBehavior>();
if (throttle == null)
{
LogWriter.PutInfo(CLASSNAME, "throttle == null");
throttle = new ServiceThrottlingBehavior();
throttle.MaxConcurrentCalls = Int32.MaxValue;
throttle.MaxConcurrentSessions = Int32.MaxValue;
throttle.MaxConcurrentInstances = Int32.MaxValue;
host.Description.Behaviors.Add(throttle);
}
app.config
<system.net>
<connectionManagement>
<add address="*" maxconnection="65535"/>
</connectionManagement>
</system.net>
I want to get some ListItems of a SharePoint 2010 List with a Win8 App. Everything works fine when I set the Credentials manually like:
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
EndpointAddress endpoint = new EndpointAddress("http://site1/site2/_vti_bin/Lists.asmx");
string listName = "{4e661b3b-d0a9-4440-b98f-3f3ef41a44a7}";
string viewName = "{f1ba8d46-ad36-40ef-b4bc-6f74ea87b5d7}";
string rowLimit = "25";
XElement ndQuery = new XElement("Query");
XElement ndViewFields = new XElement("ViewFields");
XElement ndQueryOptions = new XElement("QueryOptions");
MyService.ListsSoapClient client = new MyService.ListsSoapClient(basicHttpBinding, endpoint);
client.ClientCredentials.Windows.ClientCredential.UserName = "user";
client.ClientCredentials.Windows.ClientCredential.Password = "pw";
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
MyService.GetListItemsResponse response = await client.GetListItemsAsync(listName, viewName, ndQuery, ndViewFields, rowLimit, ndQueryOptions, null);
If I try to set the Credentials with the logged on Windows user i get the following Unauthorized error:
The HTTP request is unauthorized with client authentication scheme
'Negotiate'. The authentication header received from the server was
'Negotiate,NTLM'.
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Can you help me?
try this (use default credentials instead of specific):
private ListsSoapClient CreateListsSoapClient(string siteUrl, string siteUserName, string sitePassword)
{
var basicHttpBinding = new BasicHttpBinding
{
CloseTimeout = new TimeSpan(00, 5, 00),
OpenTimeout = new TimeSpan(00, 5, 00),
ReceiveTimeout = new TimeSpan(00, 5, 00),
SendTimeout = new TimeSpan(00, 5, 00),
TextEncoding = Encoding.UTF8,
MaxReceivedMessageSize = int.MaxValue,
MaxBufferSize = int.MaxValue,
Security =
{
Mode = BasicHttpSecurityMode.TransportCredentialOnly
},
ReaderQuotas =
{
MaxArrayLength = int.MaxValue,
MaxBytesPerRead = int.MaxValue,
MaxStringContentLength = int.MaxValue
}
};
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
var url = string.Format("{0}/_vti_bin/Lists.asmx", siteUrl);
var address = new EndpointAddress(url);
var listsSoapClient = new ListsSoapClient(basicHttpBinding, address);
listsSoapClient.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation;
listsSoapClient.ChannelFactory.Credentials.Windows.ClientCredential = new NetworkCredential(siteUserName, sitePassword);
listsSoapClient.ChannelFactory.Credentials.Windows.AllowNtlm = true;
return listsSoapClient;
}
I have a WCF service with NetNamedPipe for interprocess communication and I would like to add security on it. Everything works great without security, but when I am trying to use tranport security I am getting "InvalidCredentialException: The server has rejected the client credentials" exception. Can you please help me?
Code sample:
var netPipeBinding = new NetNamedPipeBinding() { MaxReceivedMessageSize = 2147483647, SendTimeout = TimeSpan.FromMinutes(10), ReceiveTimeout = TimeSpan.FromMinutes(10) };
netPipeBinding.ReaderQuotas.MaxDepth = 2147483647;
netPipeBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
netPipeBinding.ReaderQuotas.MaxArrayLength = 2147483647;
netPipeBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
netPipeBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
netPipeBinding.Security.Mode = NetNamedPipeSecurityMode.Transport;
netPipeBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
var host = new ServiceHost(typeof(MainService));
var netPipeEA = new EndpointAddress(new Uri("net.pipe://MyProject/ServerSide"));
var contractDescription = ContractDescription.GetContract(typeof (IMainService), typeof (MainService));
host.AddServiceEndpoint(new ServiceEndpoint(contractDescription, netPipeBinding, netPipeEA));
host.Opened += HostOnOpened;
host.Open();
...
...
private void HostOnOpened(object sender, EventArgs eventArgs)
{
var netPipeBinding = new NetNamedPipeBinding() { MaxReceivedMessageSize = 2147483647, SendTimeout = TimeSpan.FromMinutes(10), ReceiveTimeout = TimeSpan.FromMinutes(10) };
netPipeBinding.ReaderQuotas.MaxDepth = 2147483647;
netPipeBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
netPipeBinding.ReaderQuotas.MaxArrayLength = 2147483647;
netPipeBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
netPipeBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
netPipeBinding.Security.Mode = NetNamedPipeSecurityMode.Transport;
netPipeBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
DuplexChannelFactory<IMainService> channelFactory = new DuplexChannelFactory<IMainService>(new InstanceContext(new CalbackHandler()), netPipeBinding,
new EndpointAddress(IMainService));
var proxy = channelFactory.CreateChannel();
proxy.DoPing();
}
Thank you
The machine name, in this case "localhost" because you are using named pipe should be defined in the EndpointAddress URI.