基本上我需要的是一个p2p连接,现在我有一个异步服务器和客户端,它通过TcpClient
在彼此之间进行通信。问题是服务器很少检测到传入的消息,通常只收到第一条消息。我的服务器代码在这里:
public void RecieveAsync()
{
if (netStream == null) netStream = Server.GetStream();
netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);
}
public void recieveCallBack(IAsyncResult ar)
{
//try
//{
int rec = netStream.EndRead(ar);
if (rec == 0)
{
if (Disconnected != null)
{
Disconnected(this);
return;
}
}
else
{
if (DataRecieved != null)
{
string RecievedData = Encoding.ASCII.GetString(ReadBuffer, 0, rec);
DataRecieved(RecievedData);
}
ReadBuffer = new byte[1024];
}
}
并且发送数据的客户端代码在这里(包含在while循环中,用Thread.Sleep(1)
一遍又一遍地发送数据,以更新玩家位置)
public void Send(byte[] data, int index, int length)
{
//add data as state
//socket.NoDelay = true;
Buffer.BlockCopy(data, 0, writeBuffer, index, length);
if (netStream == null) netStream = TcpClient.GetStream();
netStream.BeginWrite(writeBuffer, 0, writeBuffer.Length, sendCallback, netStream);
}
private void sendCallback(IAsyncResult ar)
{
//try
//{
netStream.EndWrite(ar);
//if (ar.AsyncState != null)
//{
// byte[] buffer = (byte[])ar.AsyncState;
// socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, sendCallback, null);
// return;
//}
if (OnSend != null)
{
OnSend(this);
}
//catch (Exception ex)
//{
// System.Windows.Forms.MessageBox.Show(ex.ToString());
// return;
//}
}
默认缓冲区大小为1024,RecieveAsync
仅在netStream.DataAvailible
为真时调用,这会不断检查服务器循环。
编辑::
这是调用服务器的代码
while (true)
{
byte[] playerData = NormalText(PreparePlayerData());
server.Send(playerData, 0, playerData.Length);
if (server.Server.Connected)
{
server.netStream = server.Server.GetStream();
while (server.netStream.DataAvailable)
{
server.RecieveAsync();
server.netStream = server.Server.GetStream();
}
}
Thread.Sleep(1);
}
答案 0 :(得分:1)
在网络编程方面,它有助于了解各种方法背后的情况。对于receive方法,您可以使用
正确配置回调netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);
这会在收到数据时触发recieveCallBack(),但下面一行是它开始变得有趣的地方。同样值得注意的是,对netStream.BeginRead的单次调用只会触发一次回调。如果您想继续侦听数据,则需要再次调用netStream.BeginRead。
string RecievedData = Encoding.ASCII.GetString(ReadBuffer, 0, rec);
该框架不保证您将收到您在发送中写入的所有数据。一旦你收到了一些数据,你需要先决定它,然后再尝试将它转换回字符串。如果您还没有收到再打电话
所需的一切内容netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);
然后等待更多。
这是一个棘手的编程方面,但你显然很顺利。如果它有助于从一个工作示例向后检查方法IncomingTCPPacketHandler()(相当于你的recieveCallBack方法)here来自开源网络库networkcomms.net。