你好堆栈溢出成员。 我正在努力处理一些简单的代码,但我无法完成它。 我有这个等待连接的异步服务器。
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);
}
}
它会工作,但我无法从异步函数中拉出缓冲区(等待)。 我正在努力解决这个问题,我无法找到答案。
答案 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方法,所以我也加了。 仍然没有运气。