现在的位置: 首页 > 综合 > 正文

[Unity3d]socket通信 切换到web版本时报错SecurityException解决办法

2013年11月05日 ⁄ 综合 ⁄ 共 6052字 ⁄ 字号 评论关闭

今天苦战了一天,就跟一个Unity切换到web平台的socket通信出错苦苦纠缠了一天,问了好多大牛,但他们的回复都是我没搞过web平台下的通信或者我只专研于pc或者移动平台。看来没办法了,只能自己硬着头皮往下探究了,貌似之前flash开发就是这样,凡事碰到要跟服务器通信的都会出现老大难的权限不足的错误。

具体错误如下:

SecurityException: Unable to connect, as no valid crossdomain policy was found
System.Net.Sockets.Socket.Connect_internal (IntPtr sock, System.Net.SocketAddress sa, System.Int32& error, Boolean requireSocketPolicyFile)
System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP, Boolean requireSocketPolicy)
System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP)
System.Net.Sockets.UdpClient.DoConnect (System.Net.IPEndPoint endPoint)
System.Net.Sockets.UdpClient.Connect (System.Net.IPEndPoint endPoint)

System.Net.Sockets.UdpClient.Connect (System.String hostname, Int32 port)

这印象太深刻了,搞得我快吐血了,但这时终于搞定了,真欣慰。

之前我写过一篇有关于www访问web服务器的相同的问题,但那个稍微好解决一点,只要参考着官方文档就能解决了,我在这之前也有解决过该类问题的博客,官方的文档是:http://docs.unity3d.com/Documentation/Manual/SecuritySandbox.html,虽然全是英文,但学搞IT的看不了英文还真的很蛋疼,谁叫老美IT发达的呢,希望什么时候,互联网上技术先进的博客或者论坛都是中文的,当然有点想当然了,如果真有那么一天不知道是什么时候呢?!只能期待,下面回归正题。

我创建的服务器是C#的控制台程序,在项目工程文件里面添加以下crossdomain.xml文件,然后打开843的端口,切记这个必须打开,不然就会报错,客户端是通过这个端口来查找配置文件的。然后在运行unity切换到web平台就不会报错了。

怎么打开843端口呢?

解决办法:我们在unity的安装目录下找到一个sockpol.exe的这个一个工具,具体路径是在“...\Unity\Editor\Data\Tools\SocketPolicyServer“路径下有sockpol.exe和它的源码。如果你的服务器端是Windows平台的话,直接Copy一个sockpol.exe到服务器端,在CMD中执行
sockpol.exe --all
即可为服务器端配置好Security SandBox安全策略。

运行了之后我们会看到Hit Return to stop the server,然后如果有一个人连接上的话就会提示

incoming connection

got policy request,sending response

如果做到这一步 恭喜你能连接了。

测试地址:http://114.92.230.107/aspnet_client/system_web/chat/newchat.html

还有一个问题就是端口衍射的问题,要绑定外网IP和内网服务器的端口,不然的话外网还是不能使用聊天功能的,只能看到页面而已!

源码以后有空再上传,这时困了,睡觉觉!




源码:

Server端:

ChatClient:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Net.Sockets;

namespace TestServer
{
    class ChatClient
    {
        public static Hashtable ALLClients = new Hashtable(); // 客户列表

        private TcpClient _client;  // 客户端实体
        public string _clientIP;   // 客户端IP
        private string _clientNick; // 客户端昵称

        private byte[] data;        // 消息数据

        private bool ReceiveNick = true;

        public ChatClient(TcpClient client)
        {
            this._client = client;

            this._clientIP = client.Client.RemoteEndPoint.ToString();

            // 把当前客户端实例添加到客户列表当中
            ALLClients.Add(this._clientIP, this);

            data = new byte[this._client.ReceiveBufferSize];

            // 从服务端获取消息
            client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
        }

        // 从客戶端获取消息
        public void ReceiveMessage(IAsyncResult ar)
        {
            int bytesRead;

            try
            {
                lock (this._client.GetStream())
                {
                    bytesRead = this._client.GetStream().EndRead(ar);
                }

                if (bytesRead < 1)
                {
                    ALLClients.Remove(this._clientIP);

                    Broadcast(this._clientNick + " has left the chat");

                    return;
                }
                else
                {
                    string messageReceived = System.Text.Encoding.ASCII.GetString(data, 0, bytesRead);

                    if (ReceiveNick)
                    {
                        this._clientNick = messageReceived;

                        Broadcast(this._clientNick + " has joined the chat.");

                        //this.sendMessage("hello");

                        ReceiveNick = false;
                    }
                    else
                    {
                        Broadcast(this._clientNick + ">" + messageReceived);

                    }
                }

                lock (this._client.GetStream())
                {
                    this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
                }
            }
            catch (Exception ex)
            {
                ALLClients.Remove(this._clientIP);

                Broadcast(this._clientNick + " has left the chat.");
            }
        }

        // 向客戶端发送消息
        public void sendMessage(string message)
        {
            try
            {
                System.Net.Sockets.NetworkStream ns;

                lock (this._client.GetStream())
                {
                    ns = this._client.GetStream();
                }

                // 对信息进行编码
                byte[] bytesToSend = System.Text.Encoding.ASCII.GetBytes(message);

                ns.Write(bytesToSend, 0, bytesToSend.Length);
                ns.Flush();
            }
            catch (Exception ex)
            {

            }
        }

        // 向客户端广播消息
        public void Broadcast(string message)
        {
            Console.WriteLine(message);

            foreach (DictionaryEntry c in ALLClients)
            {
                ((ChatClient)(c.Value)).sendMessage(message + Environment.NewLine);
            }
        }

    }
}

Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using TestServer;

namespace ConsoleApplication1
{
    class Program
    {
        //设置连接端口
        const int portNo = 5001;
        static void Main(string[] args)
        {
            // 初始化服务器IP
            System.Net.IPAddress localAdd = System.Net.IPAddress.Parse("114.92.245.173");

            // 创建TCP侦听器
            TcpListener listener = new TcpListener(localAdd, portNo);

            //开始启动监听
            listener.Start();

            // 显示服务器启动信息
            Console.WriteLine("Server is starting...\n");

            // 循环接受客户端的连接请求
            while (true)
            {
                ChatClient user = new ChatClient(listener.AcceptTcpClient());

                // 显示连接客户端的IP与端口
                Console.WriteLine(user._clientIP + " is joined...\n");
            }
        }
    }
}

Client端:

using UnityEngine;
using System.Collections;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Net.Sockets;

public class ClientHandler : MonoBehaviour
{
    //端口号
    const int portNo = 50001;
    private TcpClient _client; //当前socket客户端
    byte[] data;

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    //名字
    public string nickName = "";
    //信息
    public string message = "";
    //要发送的消息
    public string sendMsg = "";

    void OnGUI()
    {
        //用户名
        nickName = GUI.TextField(new Rect(10, 10, 100, 20), nickName);
        //聊天消息
        message = GUI.TextArea(new Rect(10, 40, 300, 200), message);
        //发送的消息
        sendMsg = GUI.TextField(new Rect(10, 250, 210, 20), sendMsg);

        if (GUI.Button(new Rect(120, 10, 150, 20), "填写用户名之后连接"))
        {
			//创建一个新的连接
            this._client = new TcpClient();
            this._client.Connect("114.92.245.173", portNo);
			if(this._client.Connected)
			{
				Debug.Log("登陆成功");
			}
			//接受多大的字节数据
            data = new byte[this._client.ReceiveBufferSize];

            //发送用户名
            SendMessage(nickName);
			
            this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
        };

        if (GUI.Button(new Rect(230, 250, 80, 20), "发送"))
        {
            SendMessage(sendMsg);
            sendMsg = "";
        };
    }

    //发送消息(ASCII码)
    public void SendMessage(string message)
    {
        try
        {
			//创建流
            NetworkStream ns = this._client.GetStream();

            byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

            ns.Write(data, 0, data.Length); 
            ns.Flush();
        }
        catch (Exception ex)
        {
            //MessageBox.Show(ex.ToString());
        }
    }

    //接受消息
    public void ReceiveMessage(IAsyncResult ar)
    {
        try
        {
            int bytesRead;

            bytesRead = this._client.GetStream().EndRead(ar);
			
			//如果没有信息则返回
            if (bytesRead < 1)
            {
                return;
            }
            else
            {

                Debug.Log(System.Text.Encoding.ASCII.GetString(data, 0, bytesRead));
				//message是不断的加的,然后显示到中间的框中
                message += System.Text.Encoding.ASCII.GetString(data, 0, bytesRead);
            }
			
			//开始读取接收到的信息保存到data中
            this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);

        }
        catch (Exception ex)
        {

        }
        
    }
}

效果:

项目源文件:

http://download.csdn.net/detail/s10141303/6618107

抱歉!评论已关闭.