回复时出现 TCP 错误
TCP error on reply
我创建了一个简单的网络游戏,它使用 TCP 套接字来获取其他玩家的数据。我有两个不同的 类,一个服务器和一个客户端。当我一次只发送一条消息时,一切都很好:
客户:
public void ClientTester()
{
thread = new Thread(SendPosition);
thread.Start();
}
private void SendPosition()
{
while (true)
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "Position:", 9);
}
}
Thread.Sleep(60);
}
}
服务器:
public void ServerTester()
{
thread = new Thread(TheadedMethod);
thread.Start();
}
private void TheadedMethod()
{
while (true)
{
TcpListener listener = new TcpListener(IPAddress.Any, 82);
listener.Start();
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
parseString(msg, "Position:", 9);
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
}
listener.Stop();
}
}
这是新代码:
客户:
public void ClientTester()
{
thread = new Thread(SendPosition);
thread.Start();
SendMousePosition();
}
private void SendPosition()
{
while (true)
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "Position:", 9);
}
}
Thread.Sleep(60);
}
}
private void SendMousePosition()
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("MousePosition:" + cursor.mousePosition());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "MousePosition:", 14);
}
}
}
服务器:
public void ServerTester()
{
thread = new Thread(TheadedMethod);
thread.Start();
}
private void TheadedMethod()
{
while (true)
{
TcpListener listener = new TcpListener(IPAddress.Any, 82);
listener.Start();
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
string msg = new BinaryReader(n).ReadString();
if (msg == "Position:")
{
parseString(msg, "Position:", 9);
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
}
if (msg == "MousePosition:")
{
parseString(msg, "MousePosition:", 14);
BinaryWriter w = new BinaryWriter(n);
w.Write("MousePosition:" + cursor.mousePosition());
w.Flush();
}
}
listener.Stop();
}
}
当我尝试发送两条消息时收到错误消息:
Unable to read beyond the end of the stream.
在客户端方法 SendPosition() 的这一行中:
string msg = new BinaryReader(n).ReadString();
为什么即使我创建了一个新的 BinaryReader 实例,它仍然不起作用?服务器不应该自动响应发送给它的每条消息吗?
你做错了两件事:第一个是你一直在创建和重新创建连接。而是创建一次监听器,进入循环并读取消息。在 TCP 中建立一个新连接会增加很多开销,尤其是当您只是发送小消息时。客户端也是一样,连接一次,需要的时候发送。
第二个问题是TCP是一个streaming协议,没有消息边界。这意味着当您从 TCP 连接读取时,您无法事先知道您将读取多少数据,您需要提供一种自己分隔消息的方法:您可以添加消息边界,您可以在每条消息前加上一个包含消息大小,您的所有消息都是相同的固定大小。无论哪种方式,您可能需要阅读多次才能获得完整的信息,或者一次阅读可能会给您多条信息。
关于第二个问题,您当然不能尝试阅读超过已收到的内容,这可能是错误消息告诉您的内容。
我创建了一个简单的网络游戏,它使用 TCP 套接字来获取其他玩家的数据。我有两个不同的 类,一个服务器和一个客户端。当我一次只发送一条消息时,一切都很好:
客户:
public void ClientTester()
{
thread = new Thread(SendPosition);
thread.Start();
}
private void SendPosition()
{
while (true)
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "Position:", 9);
}
}
Thread.Sleep(60);
}
}
服务器:
public void ServerTester()
{
thread = new Thread(TheadedMethod);
thread.Start();
}
private void TheadedMethod()
{
while (true)
{
TcpListener listener = new TcpListener(IPAddress.Any, 82);
listener.Start();
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
parseString(msg, "Position:", 9);
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
}
listener.Stop();
}
}
这是新代码:
客户:
public void ClientTester()
{
thread = new Thread(SendPosition);
thread.Start();
SendMousePosition();
}
private void SendPosition()
{
while (true)
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "Position:", 9);
}
}
Thread.Sleep(60);
}
}
private void SendMousePosition()
{
using (TcpClient client = new TcpClient())
{
client.Connect("127.0.0.1", 82);
using (NetworkStream n = client.GetStream())
{
BinaryWriter w = new BinaryWriter(n);
w.Write("MousePosition:" + cursor.mousePosition());
w.Flush();
string msg = new BinaryReader(n).ReadString();
parseString(msg, "MousePosition:", 14);
}
}
}
服务器:
public void ServerTester()
{
thread = new Thread(TheadedMethod);
thread.Start();
}
private void TheadedMethod()
{
while (true)
{
TcpListener listener = new TcpListener(IPAddress.Any, 82);
listener.Start();
using (TcpClient c = listener.AcceptTcpClient())
using (NetworkStream n = c.GetStream())
{
string msg = new BinaryReader(n).ReadString();
if (msg == "Position:")
{
parseString(msg, "Position:", 9);
BinaryWriter w = new BinaryWriter(n);
w.Write("Position:" + GameFiles.Player.Player.position.ToString());
w.Flush();
}
if (msg == "MousePosition:")
{
parseString(msg, "MousePosition:", 14);
BinaryWriter w = new BinaryWriter(n);
w.Write("MousePosition:" + cursor.mousePosition());
w.Flush();
}
}
listener.Stop();
}
}
当我尝试发送两条消息时收到错误消息:
Unable to read beyond the end of the stream.
在客户端方法 SendPosition() 的这一行中:
string msg = new BinaryReader(n).ReadString();
为什么即使我创建了一个新的 BinaryReader 实例,它仍然不起作用?服务器不应该自动响应发送给它的每条消息吗?
你做错了两件事:第一个是你一直在创建和重新创建连接。而是创建一次监听器,进入循环并读取消息。在 TCP 中建立一个新连接会增加很多开销,尤其是当您只是发送小消息时。客户端也是一样,连接一次,需要的时候发送。
第二个问题是TCP是一个streaming协议,没有消息边界。这意味着当您从 TCP 连接读取时,您无法事先知道您将读取多少数据,您需要提供一种自己分隔消息的方法:您可以添加消息边界,您可以在每条消息前加上一个包含消息大小,您的所有消息都是相同的固定大小。无论哪种方式,您可能需要阅读多次才能获得完整的信息,或者一次阅读可能会给您多条信息。
关于第二个问题,您当然不能尝试阅读超过已收到的内容,这可能是错误消息告诉您的内容。