gpt4 book ai didi

c# - 在BeginConnect之后调用EndConnect

转载 作者:行者123 更新时间:2023-12-03 12:09:22 25 4
gpt4 key购买 nike

根据this MSDN article,应在原始socket.EndConnect调用中提供的AsyncCallback委托(delegate)中调用socket.BeginConnect方法。

还不清楚的是(是否在超时后(且套接字未连接),是否应调用EndConnect(MSDN文章在此处未作介绍)。在这种情况下,socket.EndConnect引发异常。

超时后应遵循的正确程序是什么?如果未调用EndConnect(成功连接之后或未连接超时)会带来什么后果?我的代码似乎可以正常工作,而无需调用EndConnect

以下是一些示例代码,涵盖了问题的主要思想:

// Member variables
private static ManualResetEvent m_event;
private static Socket m_socket;

// Constructor of class
public static CMyTestConnection()
{
// Create an event that can be used to wake this thread when the connection completes
m_event = new ManualResetEvent(false);
}

private static void TestConnection(object sender, EventArgs e)
{
// Create connection endpoint
IPAddress ip = IPAddress.Parse("200.1.2.3"); // Deliberately incorrect
IPEndPoint ipep = new IPEndPoint(ip, 12345); // Also deliberately incorrect
EndPoint ep = (EndPoint)ipep;

// Attempt connection
m_event.Reset();
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
m_socket.BeginConnect(ep, ConnectCompletedCallback, m_socket);
}

private static void ConnectCompletedCallback(IAsyncResult ar)
{
// The asynchronous connection call has completed. Either we have connected (success) or
// timed out without being able to connect (failure).
m_event.Set();
Socket s = (Socket)ar.AsyncState;
if (s.Connected)
{
// Success...should EndConnect only be called here?
s.EndConnect(ar);
}
else
{
// Or should EndConnect also be called here (in a try/catch block)?
s.Close();
}
}

最佳答案

您邀请我加入this chat room。我假设这是您要提及的问题,但是我很难确定。您在聊天室中的消息没有真实的URL。我查看了您个人资料中的问题链接,我唯一识别的是这个链接,目前尚未关闭。因此,无需重新投票就可以投票。

也就是说,答案仍然与注释中已经提供的答案相同:调用EndXXX时,始终调用BeginXXX方法(一些已知的异常(exception)不适用于此处)。即使最近进行了修改,您的问题也没有任何内容可以表明您还需要什么。

您没有显示超时的实现方式,因此甚至没有足够的信息来理解您发布的代码。但是,如果要关闭套接字,从而导致在EndConnect()将引发异常的地方调用回调,则应调用EndConnect()。否则,可能会导致无法管理的资源悬空,从而最终耗尽资源,或者至少会导致性能问题。

.NET的源代码很容易获得,因此您可以轻松地自己检查the implementation。在Socket.EndConnect()的情况下,我们可以看到,对于当前的实现,如果套接字已经被处置,那么所有发生的事情就是抛出了异常。因此,从理论上讲,您可以忽略已经关闭的套接字。 IE。在特定的“套接字已关闭”情况下,这是对使资源悬空的普遍担忧的一个异常(exception)。但仅当您的超时是通过关闭套接字实现的。

但是,这里有一些与比赛条件有关的问题:

  • 根据超时的实现方式(您没有共享该部分,因此问题仍然不完整),您可能有一些代码甚至可以开始调用Socket.Close(),但尚未设置处置标志。您将要处理即将断开的已连接套接字,并且需要使用try/catch来处理这种情况。
  • 您的回调假定(似乎…再一次,您的问题中没有足够的上下文)Connected属性是一种检测到超时的可靠方法,但是从理论上讲,可以在连接后将Connected属性重置为false,但是在连接之前您的回调将执行(例如套接字上的其他某种错误)。

  • 至于在成功连接上调用 EndConnect()的问题,那就更清楚了:您必须这样做。如果您的代码即使没有运行也能正常工作,那只是您很幸运。我们可以在实现中看到,在成功连接后调用 EndConnect()方法可以有效地配置套接字状态,因此,如果无法调用该方法,则套接字将处于不确定的,未完全配置的状态。

    自然地,如果您的超时是通过其他方式实现的,即在调用回调之前未关闭套接字,那么您的处境就像连接已经完成一样,必须调用 EndConnect()来确保进行适当的清理和套接字配置发生。 IE。这将与“成功连接”方案相同。

    最重要的是,在基于关闭/处置的超时情况下,给 而不是调用 EndConnect()会给 带来的好处。唯一的假设好处可能是您可以避免try/catch,但是由于存在竞争条件,您不能避免这样做。而且,如果没有这样的超时,不调用该方法不仅没有好处,而且如果不调用该方法,则会带来真正的危害。

    与此相关的是,您的问题中没有足够的上下文来对其余的代码进行任何实际的评估(因为您没有显示如何实现超时,也没有显示其余的网络I/O的处理方式)。但我会说,在大多数情况下,“重用地址”选项是不必要的,不应使用。大多数人之所以使用它,是因为他们陷入一种情况,即他们以某种方式停止了先前的监听套接字后无法启动新的监听套接字,但是问题仅在于第一个监听套接字和/或关联的已连接套接字没有出现已关闭或正确关闭。在这种情况下,正确的方法是正确处理套接字关闭/关闭,而不是通过设置“重用地址”来增加问题。

    关于c# - 在BeginConnect之后调用EndConnect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44569157/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com