<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dave Tucker Online</title>
	<atom:link href="http://www.davetuckeronline.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.davetuckeronline.com</link>
	<description></description>
	<lastBuildDate>Fri, 21 May 2010 14:10:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>TCP Connect Timeout In C# .NET</title>
		<link>http://www.davetuckeronline.com/2010/05/tcp-connect-timeout-in-csharp-dot-net/</link>
		<comments>http://www.davetuckeronline.com/2010/05/tcp-connect-timeout-in-csharp-dot-net/#comments</comments>
		<pubDate>Wed, 19 May 2010 19:54:26 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[Computer Programming]]></category>

		<guid isPermaLink="false">http://www.davetuckeronline.com/?p=21</guid>
		<description><![CDATA[The Connect methods of the Socket and TcpClient classes fail to provide a means to form a TCP connection while allowing for a timeout.  This is particularly inconvenient because the default timeouts tend to be long, although they vary by platform.  When forced to wait over 10 seconds for a connection to succeed, a user [...]]]></description>
			<content:encoded><![CDATA[<p>The Connect methods of the Socket and TcpClient classes fail to provide a means to form a TCP connection while allowing for a timeout.  This is particularly inconvenient because the default timeouts tend to be long, although they vary by platform.  When forced to wait over 10 seconds for a connection to succeed, a user may decide your application has locked-up.</p>
<p>Modern networks are fairly reliable, resulting in little packet loss.  If a response was not returned from a host within 1 second, it is likely because the host is down or the IP address is incorrect.  Therefor, forcing the connection attempt to timeout may be safe and efficient for some applications.</p>
<p>The code below provides a means to initiate a TCP connection, and time out after a specified duration has elapsed.  While there are many means to accomplish this, I&#8217;ve found the most stable and efficient to be the use of non-blocking sockets.  This will cause the Connect method to send the TCP syn packet and then return immediately.  The socket is then polled continuously until 1 of 3 things has happened:</p>
<ul>
<li>The connection is established</li>
<li>The timeout is reached</li>
<li>A socket error occurs</li>
</ul>
<p>If successful, the ConnectWithTimeout method will return a connected Socket object.  Otherwise, a variety of exceptions could be thrown.</p>
<pre class="code"><span class="lnr"> 1 </span><span class="Type">public</span> <span class="Type">static</span> Socket ConnectWithTimeout(<span class="Type">string</span> host, <span class="Type">int</span> port, <span class="Type">uint</span> timeout,
<span class="lnr"> 2 </span>    AddressFamily addressfamily = AddressFamily.InterNetwork,
<span class="lnr"> 3 </span>    SocketType socketType = SocketType.Stream,
<span class="lnr"> 4 </span>    ProtocolType protocolType = ProtocolType.Tcp)
<span class="lnr"> 5 </span>{
<span class="lnr"> 6 </span>    <span class="Comment">// 1 tick is 10000 milliseconds</span>
<span class="lnr"> 7 </span>    <span class="Type">const</span> <span class="Type">uint</span> MS_TO_TICKS = <span class="Constant">10000</span>;
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span>    <span class="Comment">// Wait for 1/10 of a millisecond for a socket error</span>
<span class="lnr">10 </span>    <span class="Type">const</span> <span class="Type">int</span> POLL_DURATION = <span class="Constant">100</span>;
<span class="lnr">11 </span>
<span class="lnr">12 </span>    Socket socket = <span class="Statement">new</span> Socket(addressfamily, socketType, protocolType);
<span class="lnr">13 </span>    DateTime timeoutDT = DateTime.Now;
<span class="lnr">14 </span>
<span class="lnr">15 </span>    <span class="Statement">try</span>
<span class="lnr">16 </span>    {
<span class="lnr">17 </span>        <span class="Statement">checked</span>
<span class="lnr">18 </span>        {
<span class="lnr">19 </span>            timeoutDT = DateTime.Now.AddTicks(timeout * MS_TO_TICKS);
<span class="lnr">20 </span>        }
<span class="lnr">21 </span>    }
<span class="lnr">22 </span>    <span class="Statement">catch</span> (OverflowException)
<span class="lnr">23 </span>    {
<span class="lnr">24 </span>        <span class="Statement">throw</span> <span class="Statement">new</span> ArgumentOutOfRangeException(<span class="Constant">"timeout"</span>);
<span class="lnr">25 </span>    }
<span class="lnr">26 </span>
<span class="lnr">27 </span>    socket.Blocking = <span class="Constant">false</span>;
<span class="lnr">28 </span>
<span class="lnr">29 </span>    <span class="Statement">try</span>
<span class="lnr">30 </span>    {
<span class="lnr">31 </span>        socket.Connect(host, port);
<span class="lnr">32 </span>    }
<span class="lnr">33 </span>    <span class="Statement">catch</span> (SocketException socketEx)
<span class="lnr">34 </span>    {
<span class="lnr">35 </span>        <span class="Comment">// The connect method should throw a WouldBlock error</span>
<span class="lnr">36 </span>        <span class="Statement">if</span> (socketEx.SocketErrorCode != SocketError.WouldBlock)
<span class="lnr">37 </span>        {
<span class="lnr">38 </span>            <span class="Statement">throw</span> socketEx;
<span class="lnr">39 </span>        }
<span class="lnr">40 </span>    }
<span class="lnr">41 </span>
<span class="lnr">42 </span>    <span class="Statement">while</span> (!socket.Connected)
<span class="lnr">43 </span>    {
<span class="lnr">44 </span>        <span class="Statement">if</span> (DateTime.Now &gt; timeoutDT)
<span class="lnr">45 </span>        {
<span class="lnr">46 </span>            <span class="Statement">throw</span> <span class="Statement">new</span> TimeoutException(<span class="Constant">"Timeout during connection attempt."</span>);
<span class="lnr">47 </span>        }
<span class="lnr">48 </span>
<span class="lnr">49 </span>        <span class="Statement">if</span> (socket.Poll(POLL_DURATION, SelectMode.SelectError))
<span class="lnr">50 </span>        {
<span class="lnr">51 </span>            <span class="Statement">throw</span> <span class="Statement">new</span> SocketException
<span class="lnr">52 </span>            (
<span class="lnr">53 </span>                (<span class="Type">int</span>)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Error)
<span class="lnr">54 </span>            );
<span class="lnr">55 </span>        }
<span class="lnr">56 </span>    }
<span class="lnr">57 </span>
<span class="lnr">58 </span>    <span class="Statement">return</span> socket;
<span class="lnr">59 </span>}
</pre>
<p>The following code shows how the ConnectWithTimeout Method might be used.  The most important part is correctly handling the Exceptions which might be thrown.  Of course an unspecified catch block could catch all of them, but it may be important to know <em>why</em> the connection failed.</p>
<pre class="code"><span class="lnr"> 1 </span><span class="Statement">try</span>
<span class="lnr"> 2 </span>{
<span class="lnr"> 3 </span>    <span class="Type">const</span> <span class="Type">string</span> IP_ADDRESS = <span class="Constant">"192.168.1.1"</span>;
<span class="lnr"> 4 </span>    <span class="Type">const</span> <span class="Type">int</span> PORT = <span class="Constant">80</span>;
<span class="lnr"> 5 </span>    <span class="Type">const</span> <span class="Type">uint</span> TIMEOUT = <span class="Constant">2000</span>;
<span class="lnr"> 6 </span>
<span class="lnr"> 7 </span>    Socket socket = SocketManager.ConnectWithTimeout(IP_ADDRESS, PORT, TIMEOUT);
<span class="lnr"> 8 </span>
<span class="lnr"> 9 </span>    <span class="Comment">// SUCCESS!</span>
<span class="lnr">10 </span>
<span class="lnr">11 </span>    socket.Close();
<span class="lnr">12 </span>    socket.Dispose();
<span class="lnr">13 </span>}
<span class="lnr">14 </span><span class="Statement">catch</span> (SocketException socketEx)
<span class="lnr">15 </span>{
<span class="lnr">16 </span>    <span class="Statement">switch</span> (socketEx.SocketErrorCode)
<span class="lnr">17 </span>    {
<span class="lnr">18 </span>        <span class="Statement">case</span> SocketError.ConnectionRefused:
<span class="lnr">19 </span>            <span class="Comment">// most likely the port is not open</span>
<span class="lnr">20 </span>            <span class="Statement">break</span>;
<span class="lnr">21 </span>
<span class="lnr">22 </span>        <span class="Statement">case</span> SocketError.NetworkUnreachable:
<span class="lnr">23 </span>            <span class="Comment">// network configuration problem</span>
<span class="lnr">24 </span>            <span class="Statement">break</span>;
<span class="lnr">25 </span>
<span class="lnr">26 </span>        <span class="Statement">default</span>:
<span class="lnr">27 </span>            <span class="Comment">// other socket error</span>
<span class="lnr">28 </span>            <span class="Statement">break</span>;
<span class="lnr">29 </span>    }
<span class="lnr">30 </span>}
<span class="lnr">31 </span><span class="Statement">catch</span> (TimeoutException)
<span class="lnr">32 </span>{
<span class="lnr">33 </span>    <span class="Comment">// time out while connecting to host</span>
<span class="lnr">34 </span>}
<span class="lnr">35 </span><span class="Statement">catch</span> (SecurityException)
<span class="lnr">36 </span>{
<span class="lnr">37 </span>    <span class="Comment">// we may not have permission to form connections</span>
<span class="lnr">38 </span>}
<span class="lnr">39 </span><span class="Statement">catch</span> (ArgumentOutOfRangeException)
<span class="lnr">40 </span>{
<span class="lnr">41 </span>    <span class="Comment">// the timeout was set WAY too high</span>
<span class="lnr">42 </span>}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.davetuckeronline.com/2010/05/tcp-connect-timeout-in-csharp-dot-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
