소켓 연결 시간 초과를 구성하는 방법
클라이언트가 연결이 끊긴 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 매개 변수를 조정하여 모두에 대해 변경합니다.
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 초 동안 기다릴 수 없습니까?
나는 소켓에 연결할 때 같은 문제가 있었고 아래 해결책을 생각해 냈습니다. 잘 작동합니다. `
private bool CheckConnectivityForProxyHost(string hostName, int port)
{
if (string.IsNullOrEmpty(hostName))
return false;
bool isUp = false;
Socket testSocket = null;
try
{
testSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = null;
if (testSocket != null && NetworkingCollaboratorBase.GetResolvedConnecionIPAddress(hostName, out ip))//Use a method to resolve your IP
{
IPEndPoint ipEndPoint = new IPEndPoint(ip, port);
isUp = false;
//time out 5 Sec
CallWithTimeout(ConnectToProxyServers, 5000, testSocket, ipEndPoint);
if (testSocket != null && testSocket.Connected)
{
isUp = true;
}
}
}
}
catch (Exception ex)
{
isUp = false;
}
finally
{
try
{
if (testSocket != null)
{
testSocket.Shutdown(SocketShutdown.Both);
}
}
catch (Exception ex)
{
}
finally
{
if (testSocket != null)
testSocket.Close();
}
}
return isUp;
}
private void CallWithTimeout(Action<Socket, IPEndPoint> action, int timeoutMilliseconds, Socket socket, IPEndPoint ipendPoint)
{
try
{
Action wrappedAction = () =>
{
action(socket, ipendPoint);
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
{
wrappedAction.EndInvoke(result);
}
}
catch (Exception ex)
{
}
}
private void ConnectToProxyServers(Socket testSocket, IPEndPoint ipEndPoint)
{
try
{
if (testSocket == null || ipEndPoint == null)
return;
testSocket.Connect(ipEndPoint);
}
catch (Exception ex)
{
}
}
너무 늦을 수도 있지만 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;
}
Unity와 함께 작업했고 BeginConnect 및 소켓의 다른 비동기 메서드에 문제가있었습니다.
내가 이해하지 못하는 것이 있지만 이전의 코드 샘플은 나를 위해 작동하지 않습니다.
그래서이 코드를 작성하여 작동하게했습니다. 나는 내 컴퓨터의 로컬에서도 android 및 pc로 임시 네트워크에서 테스트합니다. 도움이되기를 바랍니다.
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System;
using System.Diagnostics;
class ConnexionParameter : Guardian
{
public TcpClient client;
public string address;
public int port;
public Thread principale;
public Thread thisthread = null;
public int timeout;
private EventWaitHandle wh = new AutoResetEvent(false);
public ConnexionParameter(TcpClient client, string address, int port, int timeout, Thread principale)
{
this.client = client;
this.address = address;
this.port = port;
this.principale = principale;
this.timeout = timeout;
thisthread = new Thread(Connect);
}
public void Connect()
{
WatchDog.Start(timeout, this);
try
{
client.Connect(IPAddress.Parse(address), port);
}
catch (Exception)
{
UnityEngine.Debug.LogWarning("Unable to connect service (Training mode? Or not running?)");
}
OnTimeOver();
//principale.Resume();
}
public bool IsConnected = true;
public void OnTimeOver()
{
try
{
if (!client.Connected)
{
/*there is the trick. The abort method from thread doesn't
make the connection stop immediately(I think it's because it rise an exception
that make time to stop). Instead I close the socket while it's trying to
connect , that make the connection method return faster*/
IsConnected = false;
client.Close();
}
wh.Set();
}
catch(Exception)
{
UnityEngine.Debug.LogWarning("Connexion already closed, or forcing connexion thread to end. Ignore.");
}
}
public void Start()
{
thisthread.Start();
wh.WaitOne();
//principale.Suspend();
}
public bool Get()
{
Start();
return IsConnected;
}
}
public static class Connexion
{
public static bool Connect(this TcpClient client, string address, int port, int timeout)
{
ConnexionParameter cp = new ConnexionParameter(client, address, port, timeout, Thread.CurrentThread);
return cp.Get();
}
//http://stackoverflow.com/questions/19653588/timeout-at-acceptsocket
public static Socket AcceptSocket(this TcpListener tcpListener, int timeoutms, int pollInterval = 10)
{
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutms);
var stopWatch = new Stopwatch();
stopWatch.Start();
while (stopWatch.Elapsed < timeout)
{
if (tcpListener.Pending())
return tcpListener.AcceptSocket();
Thread.Sleep(pollInterval);
}
return null;
}
}
C #에 대한 매우 간단한 감시 장치가 있습니다.
using System.Threading;
public interface Guardian
{
void OnTimeOver();
}
public class WatchDog {
int m_iMs;
Guardian m_guardian;
public WatchDog(int a_iMs, Guardian a_guardian)
{
m_iMs = a_iMs;
m_guardian = a_guardian;
Thread thread = new Thread(body);
thread.Start(this);
}
private void body(object o)
{
WatchDog watchdog = (WatchDog)o;
Thread.Sleep(watchdog.m_iMs);
watchdog.m_guardian.OnTimeOver();
}
public static void Start(int a_iMs, Guardian a_guardian)
{
new WatchDog(a_iMs, a_guardian);
}
}
이것은 FlappySock의 대답과 비슷하지만 레이아웃과 Boolean이 반환되는 방식이 마음에 들지 않았기 때문에 콜백을 추가했습니다. Nick Miller의 답변에 대한 의견 :
내 경험상 끝점에 도달 할 수 있지만 연결을받을 수있는 끝점에 서버가 없으면 AsyncWaitHandle.WaitOne이 신호를 받지만 소켓은 연결되지 않은 상태로 유지됩니다.
그래서 나에게 반환되는 것에 의존하는 것은 위험 할 수있는 것처럼 보인다 socket.Connected
. 나는 . nullable 부울을 설정하고 콜백 함수에서 업데이트합니다. 또한 주 함수로 돌아 가기 전에 항상 결과보고를 완료하는 것은 아니라는 것을 발견했습니다. 또한이를 처리하고 시간 제한을 사용하여 결과를 기다리도록합니다.
private static bool? areWeConnected = null;
private static bool checkSocket(string svrAddress, int port)
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(svrAddress), port);
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
int timeout = 5000; // int.Parse(ConfigurationManager.AppSettings["socketTimeout"].ToString());
int ctr = 0;
IAsyncResult ar = socket.BeginConnect(endPoint, Connect_Callback, socket);
ar.AsyncWaitHandle.WaitOne( timeout, true );
// Sometimes it returns here as null before it's done checking the connection
// No idea why, since .WaitOne() should block that, but it does happen
while (areWeConnected == null && ctr < timeout)
{
Thread.Sleep(100);
ctr += 100;
} // Given 100ms between checks, it allows 50 checks
// for a 5 second timeout before we give up and return false, below
if (areWeConnected == true)
{
return true;
}
else
{
return false;
}
}
private static void Connect_Callback(IAsyncResult ar)
{
areWeConnected = null;
try
{
Socket socket = (Socket)ar.AsyncState;
areWeConnected = socket.Connected;
socket.EndConnect(ar);
}
catch (Exception ex)
{
areWeConnected = false;
// log exception
}
}
Socket 클래스에는 ReceiveTimeout 속성이 있어야합니다.
참고 URL : https://stackoverflow.com/questions/1062035/how-to-configure-socket-connect-timeout
'developer tip' 카테고리의 다른 글
Eclipse for Java에서 별도의 줄에 체인 메서드 호출 래핑 (0) | 2020.08.23 |
---|---|
NSRunLoop 이해 (0) | 2020.08.23 |
Java에서 NaN은 무엇을 의미합니까? (0) | 2020.08.23 |
색상에서 브러시로 변환 (0) | 2020.08.23 |
메모장 ++ htmltidy-libtidy.dll을 찾을 수 없음 (0) | 2020.08.23 |