结论1:tcpchannel的timeout设置对服务端处理时间过长时是起到超时作用的。
结论2:tcpchannel对连接网络慢或者网络层的执行时间太久是没有起到超时作用的。
结论3:使用新的ClientTransportSink解决了因为网络问题hang太久的问题,
测试一
服务端
class Program
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
static void Main(string[] args)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
TcpChannel chan = new TcpChannel(8080);
ChannelServices.RegisterChannel(chan,false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(ServerObject),
"ServerObject", WellKnownObjectMode.Singleton);
Console.WriteLine("server is start");
Console.Read();
chan.StopListening(null);
ChannelServices.UnregisterChannel(chan);
}
}
public class ServerObject : MarshalByRefObject
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public string SayHello(string name)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Thread.Sleep(5000);
return string.Format("Hello {0}", name);
}
}
客户端
class Program
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
static void Main(string[] args)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Hashtable props = new Hashtable();
props["name"] = "tcp_rem";
props["timeout"] = 1000;
TcpChannel _tcpChannel = new TcpChannel(props, null, null);
ChannelServices.RegisterChannel(_tcpChannel, false);
ServerObject so = (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://127.0.0.1:8080/ServerObject");
Console.WriteLine(so.SayHello("onlytiancai"));
}
catch (Exception ex)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(ex);
}
Console.Read();
}
}
一秒超时后客户端就会报以下错误
System.Net.Sockets.SocketException: 由于连接方在一段时间后没有正确答复或连接的主
机没有反应,连接尝试失败。
结论:tcpchannel的timeout设置对服务端处理时间过长时是起到超时作用的。
测试二
再做一个测试,把客户端连接的地址改成一个乱七八糟的远程地址。
ServerObject so = (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://192.192.192.192:8080/ServerObject");
这时候客户端会hang 10秒以上,也有可能hang更久。
结论:tcpchannel对连接网络慢或者网络层的执行时间太久是没有起到超时作用的。
测试三
再做一个测试,把我改进后的TcpClientTransportSink配置上,看看能不能起到超时的作用。
配置文件如下
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application >
<channels>
<channel ref="tcp">
<clientProviders>
<formatter ref="binary"/>
<provider type="WawaSoft.Remoting.Channels.Tcp.TcpClientTransportSinkProvider,WawaRemoting" />
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
客户端代码如下
class Program
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
static void Main(string[] args)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RemotingConfiguration.Configure("Client.exe.config", false);
ServerObject so = (ServerObject)Activator.GetObject(typeof(ServerObject), "tcp://192.192.192.192:8080/ServerObject");
Console.WriteLine(so.SayHello("onlytiancai"));
}
catch (Exception ex)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(ex);
}
Console.Read();
}
}
一秒后出现如下错误提示
System.ApplicationException: connect timout
Server stack trace:
在 WawaSoft.Remoting.Channels.RemoteConnection.CreateNewSocket(EndPoint ipEnd
Point) 位置 E:\huhao\project\RemotingTimeoutTest\WawaRemoting\Channels\RemoteCon
nection.cs:行号 89
结论:使用新的ClientTransportSink解决了因为网络问题hang太久的问题,但是目前的代码我只在connect上加了超时机制,send和receive还没有加超时机制,再有一个问题就是在同步调用上做超时必须另起个线程然后用join做超时,稳定性还得做压力测试来确认。
新的ClientTransportSink和测试代码见以下链接。
RemotingTimeoutTest.zip
以上代码大多都是反射与.net fx,所以稳定性应该还是很好的,只修改了RemoteConnection类的CreateNewSocket方法,如下
修改前
private SocketHandler CreateNewSocket(EndPoint ipEndPoint)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.DisableNagleDelays(socket);
socket.Connect(ipEndPoint);
this._lkgIPEndPoint = socket.RemoteEndPoint;
return this._socketCache.CreateSocketHandler(socket, this._machineAndPort);
}
修改后
![](/Images/OutliningIndicators/None.gif)
private SocketHandler CreateNewSocket(EndPoint ipEndPoint)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.Debug, 1);
Exception pingException = null;
DateTime now = DateTime.Now;
![](/Images/OutliningIndicators/InBlock.gif)
System.Threading.Thread pingThread = new System.Threading.Thread(
delegate()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
socket.Connect(ipEndPoint);
//这里不用beginConnect,太麻烦
}
catch (Exception ex)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
pingException = ex;
}
});
![](/Images/OutliningIndicators/InBlock.gif)
pingThread.Start();
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (pingThread.Join(1000))
{
if (pingException == null)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this._socketCache.CreateSocketHandler(socket, this._machineAndPort);
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
else
{throw pingException;}
}
throw new ApplicationException("connect timout");
}
改进;超时的部分想办法不用join事先,用一个waithandle实现。