【问题标题】:LAN communication for Unity3D C#Unity3D C#的局域网通信
【发布时间】:2020-10-25 14:22:10
【问题描述】:

我想让 2 台计算机在没有第三方插件的情况下使用 Unity 通过 LAN 进行通信。 我找到了一些适用于 localhost 的代码,但是当我在一台 PC 上执行服务器并在另一台 PC 上执行客户端时,我无法让它工作。

这是我目前使用的代码:

服务器:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;

public class Server: MonoBehaviour
{
    private TcpListener tcpListener;    
    private Thread tcpListenerThread;
    private TcpClient connectedTcpClient;

    void Start()
    {
        tcpListenerThread = new Thread(new ThreadStart(ListenForIncomingRequests));
        tcpListenerThread.IsBackground = true;
        tcpListenerThread.Start();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SendMessage();
        }
    }

    private void ListenForIncomingRequests()
    {
        try
        {
            tcpListener = new TcpListener(IPAddress.Any, 8052);
            tcpListener.Start();
            Debug.Log("Server is listening");
            Byte[] bytes = new Byte[1024];
            while (true)
            {
                using (connectedTcpClient = tcpListener.AcceptTcpClient())
                {
                    using (NetworkStream stream = connectedTcpClient.GetStream())
                    {
                        int length;
                        while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
                        {
                            var incomingData = new byte[length];
                            Array.Copy(bytes, 0, incomingData, 0, length);
                            string clientMessage = Encoding.ASCII.GetString(incomingData);
                            Debug.Log("client message received as: " + clientMessage);
                        }
                    }
                }
            }
        }
        catch (SocketException socketException)
        {
            Debug.Log("SocketException " + socketException.ToString());
        }

        Debug.Log("Exiting...");
    }

    private void SendMessage()
    {
        if (connectedTcpClient == null)
        {
            return;
        }

        try
        {
            NetworkStream stream = connectedTcpClient.GetStream();
            if (stream.CanWrite)
            {
                string serverMessage = "This is a message from your server.";
                byte[] serverMessageAsByteArray = Encoding.ASCII.GetBytes(serverMessage);
                stream.Write(serverMessageAsByteArray, 0, serverMessageAsByteArray.Length);
                Debug.Log("Server sent his message - should be received by client");
            }
        }
        catch (SocketException socketException)
        {
            Debug.Log("Socket exception: " + socketException);
        }
    }
}

客户:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;

public class Client : MonoBehaviour
{
    #region private members     
    private TcpClient socketConnection;
    private Thread clientReceiveThread;
    #endregion
    // Use this for initialization  
    void Start()
    {
        ConnectToTcpServer();
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SendMessage();
        }
    }
    /// <summary>   
    /// Setup socket connection.    
    /// </summary>  
    private void ConnectToTcpServer()
    {
        try
        {
            clientReceiveThread = new Thread(new ThreadStart(ListenForData));
            clientReceiveThread.IsBackground = true;
            clientReceiveThread.Start();
        }
        catch (Exception e)
        {
            Debug.Log("On client connect exception " + e);
        }
    }
    /// <summary>   
    /// Runs in background clientReceiveThread; Listens for incoming data.  
    /// </summary>     
    private void ListenForData()
    {
        try
        {
            socketConnection = new TcpClient("192.168.1.8", 8052);
            Byte[] bytes = new Byte[1024];
            while (true)
            {
                // Get a stream object for reading              
                using (NetworkStream stream = socketConnection.GetStream())
                {
                    int length;
                    // Read incoming stream into byte array.
                    while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        var incomingData = new byte[length];
                        Array.Copy(bytes, 0, incomingData, 0, length);
                        // Convert byte array to string message.                        
                        string serverMessage = Encoding.ASCII.GetString(incomingData);
                        Debug.Log("server message received as: " + serverMessage);
                    }
                }
            }
        }
        catch (SocketException socketException)
        {
            Debug.Log("Socket exception: " + socketException);
        }

        Debug.Log("Exiting...");
    }
    /// <summary>   
    /// Send message to server using socket connection.     
    /// </summary>  
    private void SendMessage()
    {
        if (socketConnection == null)
        {
            return;
        }
        try
        {
            // Get a stream object for writing.             
            NetworkStream stream = socketConnection.GetStream();
            if (stream.CanWrite)
            {
                string clientMessage = "This is a message from one of your clients.";
                // Convert string message to byte array.                 
                byte[] clientMessageAsByteArray = Encoding.ASCII.GetBytes(clientMessage);
                // Write byte array to socketConnection stream.                 
                stream.Write(clientMessageAsByteArray, 0, clientMessageAsByteArray.Length);
                Debug.Log("Client sent his message - should be received by server");
            }
        }
        catch (SocketException socketException)
        {
            Debug.Log("Socket exception: " + socketException);
        }
    }
}

当我运行客户端时,我收到此错误: 连接尝试失败,因为连接方在一段时间后没有正确响应或连接的主机没有响应

我也尝试在两台计算机上允许防火墙上的端口,但也没有用。

我错过了什么?

谢谢你, 尼克

【问题讨论】:

  • 用于监听器:tcpListener = new TcpListener(IPAddress.IPAny, 8052);然后首先启动侦听器并在侦听器的客户端使用IP地址。如果监听器和客户端在不同的机器上,它们不能是相同的 IP 地址。
  • 我用于监听:tcpListener = new TcpListener(IPAddress.Any, 8052);对于客户端,我使用了 ipconfig 中的服务器 IP 地址,但得到了相同的结果。
  • 问题可能是几件事 1) 客户端和服务器之间不是路由器。从 cmd.exe 使用 ping 来确定是否有路由 2) 可能有另一个连接使用相同的端口。从 cmd.exe >Netstat -a 并检查客户端和服务器上端口号的状态。 3) 端口被病毒检查阻塞。还有其他原因,但这是开始的地方。您还可以使用像 wireshark 或 fiddler 这样的嗅探器来帮助确定问题。嗅探器将判断是否正在发送消息以及是否正在返回响应。
  • 您好,1)从客户端ping 发现服务器没有问题。 2) netstat 不显示使用同一端口的任何其他连接。 3)我从两台计算机上都禁用了防病毒软件,但没有工作。关于wireshark,我不知道如何使用它,但我发现当我尝试从客户端连接到服务器时,我收到一条消息“4180 155.542827 192.168.1.7 192.168.1.8 TCP 66 [TCP Retransmission] 50559 → 8052 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1"。 (192.168.1.7 是客户端,192.168.1.8 是服务器)
  • 在服务器上使用 Netstat 你看到监听了吗?看起来客户端尝试连接到服务器并且连接失败,因此发生了重试。服务器需要在客户端尝试连接之前启动一个监听器。我不喜欢你的服务器。首先,服务器在 while 循环中不断运行,使用大量 CPU 资源。我更喜欢使用 Async 而不是 Syn 方法。其次,您可以使用 TCP 接收一条零字节的消息,如果您看到嗅探器结果 Len=0,我认为这正在发生。

标签: c# sockets unity3d networking lan


【解决方案1】:

我将在此处为遇到与我相同问题的任何人添加解决方案。

Unity Editor 自动添加阻止连接的防火墙规则,您需要禁用此规则,或将其设置为“如果连接安全则允许连接”。

对于那些不确定如何在此处设置防火墙规则的人,这里是我采取的步骤并且它有效(Windows 10)。

点击开始,输入“防火墙”,然后点击“具有高级安全性的Windows Defender防火墙”,点击“入站规则”,搜索前面有红色块符号的规则,名为“Unity {您的版本}编辑器”并双击它,将操作设置为“如果安全则允许连接”或禁用它。 然后,您还需要创建一个新规则,允许从特定端口的特定编辑器进行连接。

请记住使用资源监视器检查连接的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多