回复

时间:2015-05-07 07:09:41

标签: c# sockets 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的新实例,为什么这不起作用?服务器是否应该自动响应发送给它的每条消息?

1 个答案:

答案 0 :(得分:2)

你正在做两个错误:首先是你一直在创建和重新创建连接。而是创建一次监听器,进入循环并阅读消息。在TCP广告中设置新连接会产生很多开销,特别是如果您只是发送小邮件。客户端也一样,连接一次,然后在需要时发送。

第二个问题是TCP是流式协议,并且没有消息边界。这意味着当您从TCP连接中读取时,您无法预先知道要读取多少数据,您需要提供一种自己分隔消息的方法:您可以添加消息边界,您可以在每个消息前加上一个标题包含邮件大小,您已经拥有相同的固定大小的所有邮件。无论哪种方式,您可能需要多次阅读才能获得完整的消息,或者一次阅读可能会为您提供多条消息。

关于第二个问题,你当然不能尝试阅读超过收到的内容,这可能是错误信息告诉你的内容。