【发布时间】:2014-08-06 14:06:47
【问题描述】:
我正在尝试编写一个服务器来侦听端口,接受传入的客户端连接,然后将该客户端连接放入堆栈中以等待将来的消息到达。理想情况下,当消息到达时,我想触发一个事件,然后允许服务器执行操作。
我已经写了几乎所有的内容...我正在使用AcceptTCPClient() 来实际获取一个新的客户端连接,这很好。然后我创建一个线程,将套接字传递给一个保存客户端状态和一些其他数据的类。但是,我认为阻塞并等待该线程上未来传入连接的唯一方法是调用 NetworkStream.Read() 之类的东西,然后阻塞直到字节到达。
所以这是根本问题 - 我正在使用 Protobuff-net,它允许我反序列化网络流而不是单个字节数组。所以通过读取前几个字节,我必须重置读取,将网络流传递给 protobuff 反序列化方法,然后继续。
我真正想要的是一种在检测到某些字节之前一直阻塞的方法,但在我准备好之前不需要我实际读取字节。
任何人都知道如何实现这一目标?
更新
正如下面的 cmets 所建议的,这似乎不是 .Net 支持的,因此最简单的解决方案似乎是使用下面使用异步读/写的 Tsukasa 示例。
我已经编写它来消耗线路上的所有字节,然后将这些字节传递给 protobuff Deserialize 方法。
不是我想要的,但效果很好。感谢大家的帮助。
private byte[] buffer = new byte[256];
private Socket socket;
private NetworkStream networkStream;
private AsyncCallback callbackRead;
private AsyncCallback callbackWrite;
public Socket Socket
{
get { return socket; }
}
public ClientProxy(Socket clientSocket)
{
socket = clientSocket;
networkStream = new NetworkStream(clientSocket);
callbackRead = new AsyncCallback(OnReadComplete);
callbackWrite = new AsyncCallback(OnWriteComplete);
}
public void ReadAsync()
{
networkStream.BeginRead(buffer, 0, buffer.Length, callbackRead, null);
}
private void OnReadComplete(IAsyncResult ar)
{
int bytesRead = networkStream.EndRead(ar);
if (bytesRead > 0)
{
MemoryStream stream = new MemoryStream(buffer);
Message data;
data = Serializer.DeserializeWithLengthPrefix<Message>(stream, PrefixStyle.Fixed32);
if (data.Type == Chat.Type.User && data.Action == Chat.Action.Add)
{
Communication.RegisterClient(data.From, socket.Handle.ToString());
}
Communication.readMessage(data);
ReadAsync();
}
else
{
networkStream.Close();
socket.Close();
networkStream = null;
socket = null;
}
}
【问题讨论】:
-
尝试使用 TcpListener 类。
-
@user1929959... 这将有助于具体如何?
-
您应该使用缓冲的内存流并通过它从网络流中读取。
-
@user1929959,这并没有解决他的问题
-
你能再具体点吗?仅在流上放置 protobuf-net 块有什么问题吗?如果您担心线程数,我确定 protobuf-net 支持异步 IO。