在每种方法中初始化一个新套接字是件好事吗?

问题描述:

所以我试图解决在C#.NET编程的套接字,但没有好的文章/指南关于它从我看到和发现(甚至官方MSDN网站已经过时的代码)。我试图按照这个链接here,但由于它已经过时,我不确定那里的代码是否被认为是好的做法。 所以,有这样的代码:在每种方法中初始化一个新套接字是件好事吗?

public void StartListening() { 
    Socket listener = new Socket(localEP.Address.AddressFamily, 
    SocketType.Stream, ProtocolType.Tcp); 

    listener.BeginAccept(new AsyncCallback(acceptCallback), listener); 
} 

再有就是这个代码:

public void acceptCallback(IAsyncResult ar) { 
    Socket listener = (Socket) ar.AsyncState; 
    Socket handler = listener.EndAccept(ar); 
} 

为什么acceptCallback初始化一个新的插座?为什么所有的方法都要初始化一个自己的套接字?只有一个这样的全班私人插座不是更好吗?

private Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);?为什么它首先创建一个侦听器套接字然后处理套接字?这是什么意思?另外,在BeginAccept方法中作为参数传入的侦听器会发生什么?从外观上看,它只是在黑洞中死去。

最后,我会非常感谢任何和所有可以帮助我理解套接字编程的教程/文章链接。

+0

请尝试以下网页上的示例代码:https://msdn.microsoft.com/en-us/library/w89fhyex(v=vs.110).aspx。这些示例使用套接字,但您可以使用任何继承套接字类的TCP类(如TCPListener,TCPClient)。我不喜欢初始化每种方法。这是不必要的,但是如果您没有为每封邮件打开新的连接,某些Microsoft库方法无法正常工作。您发布的示例代码创建一个STATE对象,并将相同的STATE对象传递给每个事件(回调),以便代码不打开和关闭连接。 STATE对象是一个传入的参数。 – jdweng

+0

我确实已经阅读过您提供的链接,因为它仅仅是我上面发布的链接的原始版本,所以我没有将其包含在我的文章中。 你用混乱的方式表达了它(因为我提到了初始化套接字,而不是方法),但是你是否说我每次发送邮件时都需要为每条消息打开一个新套接字? 我的理解是否正确,你正在谈论的STATE对象被转换为'IAsyncResult'并作为参数传递给回调方法? – Amai

+1

在大多数情况下,您不需要为每个连接打开新的套接字。您只需要小心一些库方法会自动关闭连接,并且Microsoft很难检测连接的打开和关闭时间,而不使用实际关闭连接的方法。 IAsyncResults.AsyncState是状态对象。请参阅我之前发布的网站上的示例。 – jdweng

为什么acceptCallback会初始化一个新的套接字?

这就是BSD派生的套接字API的工作原理(并反映了TCP/IP网络堆栈如何工作)。

您创建第一个套接字,其唯一作用是等待传入连接:通过Listen(或变体)方法,然后通过Accept方法(或变体)建立连接。

其中返回另一个Socket实例,该实例将用于与一个客户端通信套接字。

初始侦听套接字继续可用于新的传入连接。

这反映了许多客户端连接到服务器的模型。

可以想象Socket被两个函数重载:1.列出并接受连接,2.代表已建立的连接。我认识到这一点,当Sun系统在80年代末用C语言编写Sun OS时,所以我无法推荐这样的建议无论如何:-)。


一旦建立了连接客户端和服务器之间的操作 - 在套接字级别 - 对称的,但它是想建立连接时,考虑服务器&客户端角色非常有用。

+0

因此,我需要一个套接字来侦听每个客户端的新客户端和额外套接字,我希望从中接收数据并将数据发送到每个客户端(每个客户端1个)? – Amai

+1

@Amai是的。 n个客户的n + 1个插座。 – Richard