如何configuration套接字连接超时

当客户端尝试连接到断开连接的IP地址时,超过15秒的时间长度超时…我们如何减less超时? 什么是configuration它的方法?

我用来build立套接字连接的代码如下:

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

我find了这个。 比接受的答案更简单,并且可以与.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放入一个select/轮询循环,其超时值等于我们愿意等待连接的时间成功。

我发现这个 Visual C ++和解释那里也弯曲对我之前解释的select/轮询机制。

根据我的经验,您不能更改每个套接字的连接超时值。 您可以全部更改(通过调整OS参数)。

我通过使用Socket.ConnectAsync方法而不是Socket.Connect方法解决了问题。 调用Socket.ConnectAsync(SocketAsyncEventArgs)后,启动定时器(timer_connection),如果时间到了,检查套接字连接是否连接(如果是(m_clientSocket.Connected)),如果没有,则popup超时错误。

 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上的海报实际上使用线程解决了他的问题 。 他有一个主线程调用其他线程运行连接代码几秒钟,然后检查套接字的连接属性:

我创build了另一个方法实际上连接套接字…主线程hibernate2秒,然后检查连接方法(这是运行在一个单独的线程),如果套接字连接好,否则抛出一个exception“超时”就这样。 再次感谢您的回馈。

你想做什么,为什么不能等15到30秒才能超时?

连接到一个套接字时,我有同样的问题,我想出了下面的解决scheme,它对我来说工作得很好。 `

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

我和Unity一起工作,并从套接字的BeginConnect和其他asynchronous方法有一些问题。

有什么比我不明白,但代码示例以前不适用于我。

所以我写了这段代码使其工作。 我使用android和pc在adhocnetworking上testing它,也在本地计算机上testing。 希望它可以帮助。

 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的答案,但我添加了一个callback,因为我不喜欢布局和如何返回布尔值。 在Nick Nick的回答中,

根据我的经验,如果可以到达终点,但terminal上没有服务器能够接收连接,则AsyncWaitHandle.WaitOne将被发送信号,但套接字将保持未连接状态

所以对我来说,似乎依靠什么返回可能是危险的 – 我更喜欢使用socket.Connected 。 我设置了一个空布尔值,并在callback函数中更新它。 我也发现它不会总是在返回主函数之前报告结果 – 我也是这样处理的,并且使用超时等待结果:

 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属性。

Socket.ReceiveTimeout属性