[c#] 소켓 연결 시간 초과를 구성하는 방법

클라이언트가 연결이 끊긴 IP 주소에 연결을 시도 할 때 15 초 이상의 시간 초과가 있습니다.이 시간 초과를 어떻게 줄일 수 있습니까? 구성하는 방법은 무엇입니까?

소켓 연결을 설정하는 데 사용하는 코드는 다음과 같습니다.

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);
}



답변

나는 이것을 찾았다. 허용되는 답변보다 간단하며 .NET v2에서 작동합니다.

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

// Connect using a timeout (5 seconds)

IAsyncResult result = socket.BeginConnect( sIP, iPort, null, null );

bool success = result.AsyncWaitHandle.WaitOne( 5000, true );

if ( socket.Connected )
{
    socket.EndConnect( result );
}
else
{
     // NOTE, MUST CLOSE THE SOCKET

     socket.Close();
     throw new ApplicationException("Failed to connect server.");
}

//... 


답변

내 테이크 :

public static class SocketExtensions
{
    /// <summary>
    /// Connects the specified socket.
    /// </summary>
    /// <param name="socket">The socket.</param>
    /// <param name="endpoint">The IP endpoint.</param>
    /// <param name="timeout">The timeout.</param>
    public static void Connect(this Socket socket, EndPoint endpoint, TimeSpan timeout)
    {
        var result = socket.BeginConnect(endpoint, null, null);

        bool success = result.AsyncWaitHandle.WaitOne(timeout, true);
        if (success)
        {
            socket.EndConnect(result);
        }
        else
        {
            socket.Close();
            throw new SocketException(10060); // Connection timed out.
        }
    }
}


답변

연결 시간 초과를 허용하기 위해 확장 클래스를 작성했습니다. Connect()라는 추가 매개 변수와 함께 표준 메소드 를 사용하는 것과 똑같이 사용하십시오 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)
            { }
        }
    }


답변

나는 C #으로 프로그램하지 않지만 C에서는 소켓을 비 블로킹으로 만든 다음 연결을 기다릴 시간과 같은 시간 제한 값으로 fd를 선택 / 폴 루프에 넣어 동일한 문제를 해결합니다. 성공하기 위해.

나는 이것을 Visual C ++ 에서 찾았고 설명은 내가 전에 설명한 선택 / 폴링 메커니즘으로 구부러져 있습니다.

내 경험상 소켓 당 연결 시간 제한 값을 변경할 수 없습니다. OS 매개 변수를 조정하여 모두에 대해 변경합니다.


답변

너무 늦을 수도 있지만 Task.WaitAny (c # 5 +)를 기반으로 한 깔끔한 솔루션이 있습니다.

 public static bool ConnectWithTimeout(this Socket socket, string host, int port, int timeout)
        {
            bool connected = false;
            Task result = socket.ConnectAsync(host, port);
            int index = Task.WaitAny(new[] { result }, timeout);
            connected = socket.Connected;
            if (!connected) {
              socket.Close();
            }

            return connected;
        }


답변

Socket.Connect 메서드 대신 Socket.ConnectAsync 메서드를 사용하여 문제를 해결했습니다. Socket.ConnectAsync (SocketAsyncEventArgs)를 호출 한 후 타이머 (timer_connection)를 시작하고, 시간이 다되면 소켓 연결이 연결되었는지 확인하고 (if (m_clientSocket.Connected)) 그렇지 않은 경우 팝업 타임 아웃 오류가 발생합니다.

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();
        }
    }


답변

MSDN에서 이것을 확인하십시오 . Socket 클래스에서 구현 된 속성으로이 작업을 수행 할 수없는 것 같습니다.

MSDN의 포스터는 실제로 스레딩을 사용하여 문제해결했습니다 . 그는 몇 초 동안 연결 코드를 실행하는 다른 스레드를 호출 한 다음 소켓의 Connected 속성을 확인하는 메인 스레드가 있습니다.

실제로 소켓에 연결된 다른 메서드를 만들었습니다. 주 스레드가 2 초 동안 잠자고 소켓이 잘 연결되어 있는지 연결 방법 (별도의 스레드에서 실행 됨)을 확인하고 그렇지 않으면 “Timed out”예외가 발생합니다. 그리고 그게 전부입니다. 보충 해 주셔서 다시 한 번 감사드립니다.

무엇을하려고하는데 왜 시간이 초과되기까지 15-30 초 동안 기다릴 수 없습니까?