带有beginReceive的c#异步服务器

时间:2013-08-31 14:22:44

标签: c# sockets

你好堆栈溢出成员。 我正在努力处理一些简单的代码,但我无法完成它。 我有这个等待连接的异步服务器。

while (clientSocket.Connected)
{             
    try
    {
        clientSocket.BeginReceive(so.buffer, 0, 200, SocketFlags.None
                                  , new AsyncCallback(wait),so);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }                
}

where so(shorted StateObject)这是我的班级:

internal class StateObject
{
    public TcpClient client;
    public byte[] buffer;

    public StateObject()
    {
        buffer = new byte[200];
        client = new TcpClient();
    }
}

我使用这个类来提供有关回调函数的信息。但是我得到the system lacked sufficient buffer space or because a queue was full。 我在实际节目中发了一小段。 一个有趣的问题是,如果我写:

while (clientSocket.Connected)
{             
    try
    {
        byte[] buffer = new byte[200];
        clientSocket.BeginReceive(buffer, 0, 200, SocketFlags.None
                                  , new AsyncCallback(wait),so);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }                
}

它会工作,但我无法从异步函数中拉出缓冲区(等待)。 我正在努力解决这个问题,我无法找到答案。

4 个答案:

答案 0 :(得分:4)

while循环不应该存在,只需在endreceive之后调用beginreceive。

这是一个很糟糕的例子,但可能会给你一些想法:

public class AsyncTCP
{

    public void StartReceive()
    {
        byte[] buffer = new byte[200];
        clientSocket.BeginReceive(buffer, 0, 200, SocketFlags.None, (state) =>
        {
            int bytesReceived = clientSocket.EndReceive(state);

            // handle buffer.

            if(bytesReceived != 0)
                StartReceive();
        } ,so);
    }
}

如果是关于在EndReceive处理程序中获取状态:

private void StartReceive()
{
    StateObject myState = new StateObject();
    myState.buffer = new byte[200];
    myState.client = _client; // or whatever

    myState.client.BeginReceive(so.buffer, 0, 200, SocketFlags.None, new AsyncCallback(wait),myState);

}

private void EndReceive(IAsyncResult result)
{
    StateObject myState = (StateObject)result.State;

    int bytesReceived = myState.client.EndReceive(result);

    // handle myState.buffer

    StartReceive();

}

我认为有更好的方法可以做到这一点,例如: - 只构建一个接收缓冲区。 - 放入一些包含长度的数据包标题/数据。

祝你好运

答案 1 :(得分:4)

如何使用一些TPL功能。所以你的代码可以简化很多

int readBytes  = await s.ReceiveTaskAsync(buffer, 0, buffer.Length);

这是扩展方法ReceiveTaskAsync

public static class SocketExtensions
{
    public static Task<int> ReceiveTaskAsync(this Socket socket, byte[] buffer, int offset, int count)
    {
        return Task.Factory.FromAsync<int>(
                       socket.BeginReceive(buffer, offset, count, SocketFlags.None, null, socket),
                       socket.EndReceive);
    }
}

答案 2 :(得分:1)

问题出在这里

while (clientSocket.Connected)//checks connected
{             
    try
    {
        clientSocket.BeginReceive(so.buffer, 0, 200, SocketFlags.None, new AsyncCallback(wait),so);//says begin receive and continues to do endlessly
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex.Message);
     }                
}

只有在收到数据后才能再次拨打BeginReceive

以下是msdn如何做到的示例。

答案 3 :(得分:-1)

我解决了我之前的问题(我只需要删除while循环,但是我用同步服务器中的一些代码搞砸了)。 现在我有另一个问题,所以我将使用同一个线程。 根据我的搜索和理解,您可以像这样(主要方法)使用BecinAccept打开异步服务器:

IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 8082);

TcpListener tcpListener = new TcpListener(IPAddress.Any, 8082);           

server = tcpListener.Server;
server.Bind(ipEndPoint);
server.Listen(4);

server.BeginAccept(new AsyncCallback(beginConnection), server);

然后:

static void beginConnection(IAsyncResult iar)
        {
            Console.WriteLine("Client connected");
            Socket s = (Socket)iar.AsyncState;
            server = s.EndAccept(iar);

            server.Listen(4); // this line was initially absent
            server.BeginAccept(beginConnection, s);
        }

我希望能够连接到此服务器的多个客户端。 但是,当我尝试这样做时,只有第一个客户端连接自己。 客户端它是一个简单的套接字,它只是从服务器回送,我们从控制台读取的内容。 我认为,因为在main方法中我称为server.Listen(4),我将能够连接4个客户端。 然后我想到在beginConnection方法中递归调用BeginAccept。 最后,我收到了错误,我必须先调用Listen方法,所以我也加了。 仍然没有运气。