简体   繁体   English

了解C#中的异步(套接字)

[英]Understanding the Async (sockets) in C#

I am a little bit confused about what does the Async approach achieve. 我对异步方法能实现什么感到有些困惑。 I encountered it when looking up how to make a server accept multiple connections. 我在查找如何使服务器接受多个连接时遇到了它。 What confuses me while looking up what Aync does in C# exactly, is that from what I can tell its not its own thread. 在确切地查找Aync在C#中的功能时,令我感到困惑的是,从我可以知道其不是自己的线程的角度来看。 However, it also allows you to avoid locking and stalling. 但是,它也可以避免锁定和停转。 For instance, if I have the following: 例如,如果我有以下内容:

    ConnectionManager()
    {
        listener = new TcpListener(port);
        listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener);
    }

    public void acceptConnection(IAsyncResult ar)
    {
        //Do stuff
    }

does this mean that as soon as it finds a connection, it executes the "acceptConnection" function but then continues to execute through the caller function? 这是否意味着一旦找到连接,便会执行“ acceptConnection”函数,然后继续通过调用者函数执行? (in this case going out of scope). (在这种情况下超出范围)。 How does this allow me to create a server application that will be able to take multiple clients? 这如何使我创建一个能够容纳多个客户端的服务器应用程序? I am fairly new to this concept even though I have worked with threads before to manage server/client interaction. 尽管我之前使用过线程来管理服务器/客户端交互,但是我对这个概念还是比较陌生的。 If I am being a little vague, please let me know. 如果我有点含糊,请告诉我。 I have looked up multiple examples on MSDN and am still a little confused. 我在MSDN上查找了多个示例,但仍然有些困惑。 Thank you ahead of time! 提前谢谢你!

as soon as it finds a connection, it executes the "acceptConnection" function 找到连接后,便立即执行“ acceptConnection”功能

Yes

then continues to execute through the caller function? 然后继续通过调用者函数执行?

No. 没有。

what does the Async approach achieve 异步方法实现了什么

When done right, it allows processing much higher number of requests/second using fewer resources. 如果操作正确,它可以使用更少的资源处理每秒更高数量的请求。

Imagine you're creating a server that should accept connections on 10 TCP ports. 假设您正在创建一个服务器,该服务器应接受10个TCP端口上的连接。

With blocking API, you'll have to create 10 threads just for accepting sockets. 使用阻塞API,您仅需创建10个线程即可接受套接字。 Threads are expensive system resource, eg every thread has its own stack, and switching between threads takes considerable time. 线程是昂贵的系统资源,例如,每个线程都有自己的堆栈,并且在线程之间进行切换需要花费大量时间。 If a client connecting to some socket, the OS will have to wake up the corresponding thread. 如果客户端连接到某个套接字,则操作系统将必须唤醒相应的线程。

With async API, you post 10 asynchronous requests. 使用异步API,您可以发布10个异步请求。 When client is connecting, your acceptConnection method will be called by a thread from the CLR thread pool. 客户端连接时,CLR线程池中的线程将调用您的acceptConnection方法。

And one more thing. 还有一件事。

If you want to continue executing the caller function after waiting for asynchronous I/O operation to complete, you should consider new C#'s async/await syntax, it allows you to do just that. 如果要在等待异步I / O操作完成后继续执行调用者函数,则应考虑新C#的async / await语法,它允许您执行此操作。 The feature is available as a stand-alone library “Async CTP” for visual studio 2010, and included in visual studio 2012. 该功能可以作为独立库“ Async CTP”用于Visual Studio 2010,并包含在Visual Studio 2012中。

I don't profess to be ac# or sockets guru but from what I understand the code you've got above will accept the first connection and then no more. 我不认为自己是ac#或套接字大师,但据我了解,您上面的代码将接受第一个连接,然后不再接受。 You would need to establish another BeginAccept. 您将需要建立另一个BeginAccept。

Something like: 就像是:

TcpListener listener = null;

ConnectionManager()
{
    listener = new TcpListener(port);
    listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener);
}

public void acceptConnection(IAsyncResult ar)
{
    // Create async receive data code..

    // Get ready for a new connection
    listener.BeginAcceptSocket(new AsyncCallback(acceptConnection), listener);

}

So by using Async receive data in addition to the async connection, the accept connection finishes pretty quickly and sets up listening for a new connection. 因此,除了使用异步连接之外,通过使用异步接收数据,accept连接可以很快完成,并设置侦听新连接。 I guess you could re-order this too. 我想您也可以重新订购。

For straight socket connection (not TcpListener) this is what i used: 对于直接套接字连接(不是TcpListener),这是我使用的:

(connectedClient is a my own class which handles the receive & transmit functions and holds other info about the connection). (connectedClient是我自己的类,用于处理接收和发送功能并保存有关连接的其他信息)。

int Port = 7777; // or whatever port you want to listen on
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
listenSocket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

listenSocket.Bind(ipLocal);

// create the call back for any client connections...
        listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);

private void OnClientConnection(IAsyncResult asyn)
    {
        if (socketClosed)
        {
            return;
        }

        try
        {
            Socket clientSocket = listenSocket.EndAccept(asyn);

            ConnectedClient connectedClient = new ConnectedClient(clientSocket, this);

            connectedClient.MessageReceived += OnMessageReceived;
            connectedClient.Disconnected += OnDisconnection;
            connectedClient.MessageSent += OnMessageSent;

            connectedClient.StartListening();

            // create the call back for any client connections...
            listenSocket.BeginAccept(new AsyncCallback(OnClientConnection), null);

        }
        catch (ObjectDisposedException excpt)
        {
            // Deal with this, your code goes here

        }
        catch (Exception excpt)
        {
            // Deal with this, your code goes here
        }

    }

I hope this has answered what you're looking for ? 我希望这能回答您的要求吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM