1

嗨堆栈溢出成员。我正在为一些简单的代码而苦苦挣扎,但我无法完成它。我有这个等待连接的异步服务器。

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

所以(简称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

4 回答 4

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);
    }
}
于 2013-08-31T14:39:50.193 回答
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();

}

我认为有更好的方法可以做到这一点,比如: - 只构建一个接收缓冲区。- 在其中放入一些具有长度的数据包头/数据。

祝你好运

于 2013-08-31T14:26:38.200 回答
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的示例如何做到这一点。

于 2013-08-31T14:32:13.133 回答
-1

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

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

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

于 2013-08-31T20:02:57.243 回答