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

原文地址:传送门

今天苦战了一天,就跟一个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:

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;
  6. using System.Net.Sockets;
  7. namespace TestServer
  8. {
  9. class ChatClient
  10. {
  11. public static Hashtable ALLClients = new Hashtable(); // 客户列表
  12. private TcpClient _client; // 客户端实体
  13. public string _clientIP; // 客户端IP
  14. private string _clientNick; // 客户端昵称
  15. private byte[] data; // 消息数据
  16. private bool ReceiveNick = true;
  17. public ChatClient(TcpClient client)
  18. {
  19. this._client = client;
  20. this._clientIP = client.Client.RemoteEndPoint.ToString();
  21. // 把当前客户端实例添加到客户列表当中
  22. ALLClients.Add(this._clientIP, this);
  23. data = new byte[this._client.ReceiveBufferSize];
  24. // 从服务端获取消息
  25. client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
  26. }
  27. // 从客戶端获取消息
  28. public void ReceiveMessage(IAsyncResult ar)
  29. {
  30. int bytesRead;
  31. try
  32. {
  33. lock (this._client.GetStream())
  34. {
  35. bytesRead = this._client.GetStream().EndRead(ar);
  36. }
  37. if (bytesRead < 1)
  38. {
  39. ALLClients.Remove(this._clientIP);
  40. Broadcast(this._clientNick + " has left the chat");
  41. return;
  42. }
  43. else
  44. {
  45. string messageReceived = System.Text.Encoding.ASCII.GetString(data, 0, bytesRead);
  46. if (ReceiveNick)
  47. {
  48. this._clientNick = messageReceived;
  49. Broadcast(this._clientNick + " has joined the chat.");
  50. //this.sendMessage("hello");
  51. ReceiveNick = false;
  52. }
  53. else
  54. {
  55. Broadcast(this._clientNick + ">" + messageReceived);
  56. }
  57. }
  58. lock (this._client.GetStream())
  59. {
  60. this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
  61. }
  62. }
  63. catch (Exception ex)
  64. {
  65. ALLClients.Remove(this._clientIP);
  66. Broadcast(this._clientNick + " has left the chat.");
  67. }
  68. }
  69. // 向客戶端发送消息
  70. public void sendMessage(string message)
  71. {
  72. try
  73. {
  74. System.Net.Sockets.NetworkStream ns;
  75. lock (this._client.GetStream())
  76. {
  77. ns = this._client.GetStream();
  78. }
  79. // 对信息进行编码
  80. byte[] bytesToSend = System.Text.Encoding.ASCII.GetBytes(message);
  81. ns.Write(bytesToSend, 0, bytesToSend.Length);
  82. ns.Flush();
  83. }
  84. catch (Exception ex)
  85. {
  86. }
  87. }
  88. // 向客户端广播消息
  89. public void Broadcast(string message)
  90. {
  91. Console.WriteLine(message);
  92. foreach (DictionaryEntry c in ALLClients)
  93. {
  94. ((ChatClient)(c.Value)).sendMessage(message + Environment.NewLine);
  95. }
  96. }
  97. }
  98. }

Program:

[csharp] view plain copy print ?

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net.Sockets;
  6. using TestServer;
  7. namespace ConsoleApplication1
  8. {
  9. class Program
  10. {
  11. //设置连接端口
  12. const int portNo = 5001;
  13. static void Main(string[] args)
  14. {
  15. // 初始化服务器IP
  16. System.Net.IPAddress localAdd = System.Net.IPAddress.Parse("114.92.245.173");
  17. // 创建TCP侦听器
  18. TcpListener listener = new TcpListener(localAdd, portNo);
  19. //开始启动监听
  20. listener.Start();
  21. // 显示服务器启动信息
  22. Console.WriteLine("Server is starting...\n");
  23. // 循环接受客户端的连接请求
  24. while (true)
  25. {
  26. ChatClient user = new ChatClient(listener.AcceptTcpClient());
  27. // 显示连接客户端的IP与端口
  28. Console.WriteLine(user._clientIP + " is joined...\n");
  29. }
  30. }
  31. }
  32. }

Client端:

[csharp] view plain copy print ?

  1. using UnityEngine;
  2. using System.Collections;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel;
  6. using System.Text;
  7. using System.Net.Sockets;
  8. public class ClientHandler : MonoBehaviour
  9. {
  10. //端口号
  11. const int portNo = 50001;
  12. private TcpClient _client; //当前socket客户端
  13. byte[] data;
  14. // Use this for initialization
  15. void Start()
  16. {
  17. }
  18. // Update is called once per frame
  19. void Update()
  20. {
  21. }
  22. //名字
  23. public string nickName = "";
  24. //信息
  25. public string message = "";
  26. //要发送的消息
  27. public string sendMsg = "";
  28. void OnGUI()
  29. {
  30. //用户名
  31. nickName = GUI.TextField(new Rect(10, 10, 100, 20), nickName);
  32. //聊天消息
  33. message = GUI.TextArea(new Rect(10, 40, 300, 200), message);
  34. //发送的消息
  35. sendMsg = GUI.TextField(new Rect(10, 250, 210, 20), sendMsg);
  36. if (GUI.Button(new Rect(120, 10, 150, 20), "填写用户名之后连接"))
  37. {
  38. //创建一个新的连接
  39. this._client = new TcpClient();
  40. this._client.Connect("114.92.245.173", portNo);
  41. if(this._client.Connected)
  42. {
  43. Debug.Log("登陆成功");
  44. }
  45. //接受多大的字节数据
  46. data = new byte[this._client.ReceiveBufferSize];
  47. //发送用户名
  48. SendMessage(nickName);
  49. this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
  50. };
  51. if (GUI.Button(new Rect(230, 250, 80, 20), "发送"))
  52. {
  53. SendMessage(sendMsg);
  54. sendMsg = "";
  55. };
  56. }
  57. //发送消息(ASCII码)
  58. public void SendMessage(string message)
  59. {
  60. try
  61. {
  62. //创建流
  63. NetworkStream ns = this._client.GetStream();
  64. byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
  65. ns.Write(data, 0, data.Length);
  66. ns.Flush();
  67. }
  68. catch (Exception ex)
  69. {
  70. //MessageBox.Show(ex.ToString());
  71. }
  72. }
  73. //接受消息
  74. public void ReceiveMessage(IAsyncResult ar)
  75. {
  76. try
  77. {
  78. int bytesRead;
  79. bytesRead = this._client.GetStream().EndRead(ar);
  80. //如果没有信息则返回
  81. if (bytesRead < 1)
  82. {
  83. return;
  84. }
  85. else
  86. {
  87. Debug.Log(System.Text.Encoding.ASCII.GetString(data, 0, bytesRead));
  88. //message是不断的加的,然后显示到中间的框中
  89. message += System.Text.Encoding.ASCII.GetString(data, 0, bytesRead);
  90. }
  91. //开始读取接收到的信息保存到data中
  92. this._client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(this._client.ReceiveBufferSize), ReceiveMessage, null);
  93. }
  94. catch (Exception ex)
  95. {
  96. }
  97. }
  98. }

效果:

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

项目源文件:

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

上一篇:Echarts 数据视图 生成Excel的方法


下一篇:敲点JavaScript代码