views:

5814

answers:

5

(C# )When the Client tries to connect to a disconnected IP address, there is a long timeout over 15 seconds... How can we reduce this timeout? What is the method to config it?

The code I'm using to set up a socket connection is as following:

try
{
    m_clientSocket = new Socket(
         AddressFamily.InterNetwork,
         SocketType.Stream,
         ProtocolType.Tcp);

    IPAddress ip = IPAddress.Parse(serverIp);
    int iPortNo = System.Convert.ToInt16(serverPort);
    IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);

    m_clientSocket.Connect(ipEnd);
    if (m_clientSocket.Connected)
    {
        lb_connectStatus.Text = "Connection Established";
        WaitForServerData();
    }
}
catch (SocketException se)
{
    lb_connectStatus.Text = "Connection Failed";
    MessageBox.Show(se.Message);
}
A: 

There should be a ReceiveTimeout property in the Socket class.

Socket.ReceiveTimeout Property

Colin
I tried. It just doesn't work. I added m_clientSocket.ReceiveTimeout = 1000; before invoked the m_clientSocket.Connect(ipEnd). However, it still waits around 15-20 secs before popup the exception message.
ninikin
This sets the timeout for when the socket is receiving data after the connection has been made.
ecounysis
A: 

Check this out on MSDN. It does not appear that you can do this with the implemented properties in the Socket class.

The poster on MSDN actually solved his problem using threading. He had a main thread which called out to other threads which run the connection code for a couple seconds and then check the Connected property of the socket:

I created another method wich actually connected the socket ... had the main thread sleep for 2 seconds and then check on the connecting method (wich is run in a separate thread) if the socket was connected good otherwise throw an exception "Timed out " and that;s all. Thanks again for the repleies.

What are you trying to do, and why can't it wait for 15-30 seconds before timing out?

ecounysis
+1  A: 

I dont program in C# but in C, we solve the same problem by making the socket non-blocking and then putting the fd in a select/poll loop with a timeout value equal to the amount of time we are willing to wait for the connect to succeed.

I found this for Visual C++ and the explanation there also bends towards the select/poll mechanism I explained before.

In my experience, you cannot change connect timeout values per socket. You change it for all (by tuning OS parameters).

Aditya Sehgal
+1  A: 

I solved the problem by using Socket.ConnectAsync Method instead of Socket.Connect Method. After invoking the Socket.ConnectAsync(SocketAsyncEventArgs), start a timer (timer_connection), if time is up, check whether socket connection is connected (if(m_clientSocket.Connected)), if not, pop up timeout error.

private void connect(string ipAdd,string port)
    {
        try
        {
            SocketAsyncEventArgs e=new SocketAsyncEventArgs();


            m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress ip = IPAddress.Parse(serverIp);
            int iPortNo = System.Convert.ToInt16(serverPort);
            IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);

            //m_clientSocket.
            e.RemoteEndPoint = ipEnd;
            e.UserToken = m_clientSocket;
            e.Completed+=new EventHandler<SocketAsyncEventArgs>(e_Completed);                
            m_clientSocket.ConnectAsync(e);

            if (timer_connection != null)
            {
                timer_connection.Dispose();
            }
            else
            {
                timer_connection = new Timer();
            }
            timer_connection.Interval = 2000;
            timer_connection.Tick+=new EventHandler(timer_connection_Tick);
            timer_connection.Start();
        }
        catch (SocketException se)
        {
            lb_connectStatus.Text = "Connection Failed";
            MessageBox.Show(se.Message);
        }
    }
private void e_Completed(object sender,SocketAsyncEventArgs e)
    {
        lb_connectStatus.Text = "Connection Established";
        WaitForServerData();
    }
    private void timer_connection_Tick(object sender, EventArgs e)
    {
        if (!m_clientSocket.Connected)
        {
            MessageBox.Show("Connection Timeout");
            //m_clientSocket = null;

            timer_connection.Stop();
        }
    }
ninikin
When the timer stops, you show an error message right? How does this stop your TCP stack from actually connecting. Imagine a scenario, where a remote host is more than 2 seconds away i.e. rto > 2. Your timer will stop and you will print the error message. However, TCP is not controlled by your timer. It will still try to connect and may connect successfully after 2 seconds. Does C# provide a facility to cancel "connect" requests or a close on socket. Your timer solution is equal to checking after 2 second whether connection succeeded.
Aditya Sehgal
I found this : http://splinter.com.au/blog/?p=28 Looks like this is the way. It is similar to yours but I think it does what I explained above.
Aditya Sehgal
Hey! You guys found my blog! :)
Chris
When it times out, you should call m_clientSocket.Close();
Vincent McNabb
+2  A: 

Hi, I just wrote an extension class in order to allow timeouts in connections. Use it exactly as you would use the standard Connect() methods, with an extra parameter named timeout.

using System;
using System.Net;
using System.Net.Sockets;

/// <summary>
/// Extensions to Socket class
/// </summary>
public static class SocketExtensions
{
    /// <summary>
    /// Connects the specified socket.
    /// </summary>
    /// <param name="socket">The socket.</param>
    /// <param name="host">The host.</param>
    /// <param name="port">The port.</param>
    /// <param name="timeout">The timeout.</param>
    public static void Connect(this Socket socket, string host, int port, TimeSpan timeout)
    {
        AsyncConnect(socket, (s, a, o) => s.BeginConnect(host, port, a, o), timeout);
    }

    /// <summary>
    /// Connects the specified socket.
    /// </summary>
    /// <param name="socket">The socket.</param>
    /// <param name="addresses">The addresses.</param>
    /// <param name="port">The port.</param>
    /// <param name="timeout">The timeout.</param>
    public static void Connect(this Socket socket, IPAddress[] addresses, int port, TimeSpan timeout)
    {
        AsyncConnect(socket, (s, a, o) => s.BeginConnect(addresses, port, a, o), timeout);
    }

    /// <summary>
    /// Asyncs the connect.
    /// </summary>
    /// <param name="socket">The socket.</param>
    /// <param name="connect">The connect.</param>
    /// <param name="timeout">The timeout.</param>
    private static void AsyncConnect(Socket socket, Func<Socket, AsyncCallback, object, IAsyncResult> connect, TimeSpan timeout)
    {
        var asyncResult = connect(socket, null, null);
        if (!asyncResult.AsyncWaitHandle.WaitOne(timeout))
        {
            try
            {
                socket.EndConnect(asyncResult);
            }
            catch (SocketException)
            { }
            catch (ObjectDisposedException)
            { }
        }
    }
picrap