C# ReadAsync在异步TcpClient中仅读取一次
我编写了一个简单的异步TcpClient。以下是守则的相关部分:C# ReadAsync在异步TcpClient中仅读取一次,c#,C#,我编写了一个简单的异步TcpClient。以下是守则的相关部分: public class AsyncTcpClient : IDisposable { private TcpClient tcpClient; private Stream stream; private int bufferSize = 8192; bool IsReceiving = false; public event EventHandler<string> On
public class AsyncTcpClient : IDisposable
{
private TcpClient tcpClient;
private Stream stream;
private int bufferSize = 8192;
bool IsReceiving = false;
public event EventHandler<string> OnDataReceived;
public event EventHandler OnDisconnected;
public event EventHandler OnConnected;
public event EventHandler<Exception> OnError;
public bool IsConnected
{
get
{
return tcpClient != null && tcpClient.Connected;
}
}
public AsyncTcpClient() { }
public async Task ConnectAsync(string host, int port, CancellationToken token = default(CancellationToken))
{
try
{
if (IsConnected) Close();
tcpClient = new TcpClient();
if (!tcpClient.ConnectAsync(host, port).Wait(250))
{
throw new TimeoutException();
}
stream = tcpClient.GetStream();
OnConnected?.Invoke(this, EventArgs.Empty);
await Receive();
}
catch (Exception)
{
OnDisconnected?.Invoke(this, EventArgs.Empty);
}
}
public async Task Receive(CancellationToken token = default(CancellationToken))
{
try
{
if (!IsConnected || IsReceiving) throw new InvalidOperationException();
IsReceiving = true;
byte[] buffer = new byte[bufferSize];
while (IsConnected)
{
token.ThrowIfCancellationRequested();
// First time it reads the incoming data, then it hangs here forever
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token);
if (bytesRead > 0)
{
byte[] data = new byte[bytesRead];
Array.Copy(buffer, data, bytesRead);
OnDataReceived?.Invoke(this, Encoding.ASCII.GetString(data));
}
buffer = new byte[bufferSize];
}
}
catch (ObjectDisposedException) { }
catch (IOException)
{
throw;
}
finally
{
IsReceiving = false;
}
}
}
公共类AsyncTcpClient:IDisposable
{
私人TCP客户TCP客户;
私有流;
私有int bufferSize=8192;
bool IsReceiving=false;
已接收公共事件事件处理程序OnDataReceived;
公共事件事件处理程序未连接;
未连接的公共事件事件处理程序;
公共事件事件处理程序OnError;
公共图书馆断开了
{
收到
{
返回tcpClient!=null&&tcpClient.Connected;
}
}
公共异步TCPClient(){}
公共异步任务ConnectAsync(字符串主机,int端口,CancellationToken令牌=默认值(CancellationToken))
{
尝试
{
如果(断开连接)关闭();
tcpClient=新的tcpClient();
如果(!tcpClient.ConnectAsync(主机、端口).Wait(250))
{
抛出新的TimeoutException();
}
stream=tcpClient.GetStream();
OnConnected?.Invoke(此为EventArgs.Empty);
等待接收();
}
捕获(例外)
{
OnDisconnected?.Invoke(此为EventArgs.Empty);
}
}
公共异步任务接收(CancellationToken=默认值(CancellationToken))
{
尝试
{
如果(!IsConnected | | IsReceiving)抛出新的InvalidOperationException();
IsReceiving=真;
字节[]缓冲区=新字节[bufferSize];
while(断开连接)
{
token.ThrowIfCancellationRequested();
//它第一次读取传入的数据,然后永远挂在这里
int bytesRead=wait stream.ReadAsync(buffer,0,buffer.Length,token);
如果(字节读取>0)
{
字节[]数据=新字节[字节读取];
复制(缓冲区、数据、字节读取);
OnDataReceived?Invoke(这是Encoding.ASCII.GetString(数据));
}
buffer=新字节[bufferSize];
}
}
catch(ObjectDisposedException){}
捕获(IOException)
{
投
}
最后
{
IsReceiving=假;
}
}
}
在另一个应用程序上,我有一个等待连接的TcpListener。
成功连接后,服务器向客户端发送一些数据。从ReadAsync正确接收数据。然后,如果我尝试从服务器发送更多数据,客户端将在第二次调用ReadAsync时永远等待
我非常确定服务器正在工作,因为我收到了发送了正确字节的SendCallback
我是否错误地使用了ReadAsync
使现代化
我在这里添加我的服务器的完整的代码:
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 4096;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
public class TcpServerAsync
{
public readonly ConcurrentQueue<String> queue = new ConcurrentQueue<String>();
public ManualResetEvent allDone = new ManualResetEvent(false);
private Boolean _isRunning = true;
public event EventHandler Connected;
public TcpServerAsync(Int32 port)
{
}
public void Start()
{
Thread t = new Thread(Run);
t.Start();
}
public void Run()
{
IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
IPAddress ipAddress = ipHostInfo.AddressList[1];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5000);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(1);
while (_isRunning)
{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allDone.WaitOne();
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
public void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Connected.Invoke(this, new EventArgs());
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject
{
workSocket = handler
};
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
while (handler.Connected)
{
if (queue.TryDequeue(out String data))
{
try
{
SendData(handler, data);
}
catch (Exception ex)
{
throw;
}
}
Thread.Sleep(0);
}
}
public void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
content = state.sb.ToString();
Debug.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
}
}
public void SendData(Socket handler, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
Debug.WriteLine("Sent {0} bytes to client.", bytesSent);
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
}
公共类StateObject
{
公共套接字工作组=null;
public const int BufferSize=4096;
公共字节[]缓冲区=新字节[BufferSize];
公共StringBuilder sb=新StringBuilder();
}
公共类TcpServerAsync
{
public readonly ConcurrentQueue=new ConcurrentQueue();
public ManualResetEvent allDone=新的ManualResetEvent(false);
私有布尔值_isRunning=true;
公共事件事件处理程序已连接;
公共TcpServerAsync(Int32端口)
{
}
公开作废开始()
{
螺纹t=新螺纹(运行);
t、 Start();
}
公开募捐
{
IPHostEntry ipHostInfo=Dns.GetHostEntry(“本地主机”);
IPAddress IPAddress=ipHostInfo.AddressList[1];
IPEndPoint localEndPoint=新IPEndPoint(ipAddress,5000);
套接字侦听器=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
尝试
{
Bind(localEndPoint);
听,听(1);
当(\u正在运行)
{
全部完成。重置();
beginacept(新的异步回调(AcceptCallback),listener);
全部完成。WaitOne();
}
}
捕获(例外e)
{
Debug.WriteLine(例如ToString());
}
}
公共无效接受回调(IAsyncResult ar)
{
allDone.Set();
调用(这个,新的EventArgs());
套接字侦听器=(套接字)ar.AsyncState;
套接字处理程序=listener.EndAccept(ar);
StateObject状态=新的StateObject
{
工作组=处理程序
};
BeginReceive(state.buffer,0,StateObject.BufferSize,0,新异步回调(ReadCallback),state);
while(handler.Connected)
{
if(queue.TryDequeue(输出字符串数据))
{
尝试
{
SendData(处理程序,数据);
}
捕获(例外情况除外)
{
投
}
}
睡眠(0);
}
}
公共void ReadCallback(IAsyncResult ar)
{
String content=String.Empty;
StateObject状态=(StateObject)ar.AsyncState;
套接字处理程序=state.workSocket;
int bytesRead=handler.EndReceive(ar);
如果(字节读取>0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
content=state.sb.ToString();
WriteLine(“从套接字读取{0}字节。\n数据:{1}”,content.Length,content);
}
}
公共void SendData(套接字处理程序、字符串数据)
{
byte[]byteData=Encoding.ASCII.GetBytes(数据);
BeginSend(byteData,0,byteData.Length,0,新异步回调(SendCallback),handler);
}
私有void SendCallback(IAsyncResult ar)
{
尝试
{
套接字处理程序=(套接字)ar.AsyncState;
int bytesSent=handler.EndSend(ar);
WriteLine(“向客户端发送了{0}个字节。”,bytesSent);
}
抓住
public void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
if (Connected != null)
{
Connected.Invoke(this, new EventArgs());
}
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
BeginReceive(handler);
//while (handler.Connected)
//{
// if (queue.TryDequeue(out String data))
// {
// try
// {
// SendData(handler, data);
// }
// catch (Exception ex)
// {
// throw;
// }
// }
// Thread.Sleep(0);
//}
}
public void BeginReceive(Socket handler)
{
StateObject state = new StateObject
{
workSocket = handler
};
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
public void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (queue.TryDequeue(out String data))
{
try
{
SendData(handler, data);
}
catch (Exception ex)
{
throw;
}
}
//SendData(handler, content);
Debug.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
}
BeginReceive(handler);
}