[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安全策略。

上述步驟完成後,接著就是在 Socket 連接之前,使用 Security.PrefetchSocketPolicy( ip, port ); 這個 API,即可正常在 Web 平台上使用 Socket。 

运行了之后我们会看到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


==================== 迂者 丁小未 CSDN博客专栏=================

MyBlog:http://blog.csdn.net/dingxiaowei2013             MyQQ:1213250243

Unity QQ群:858550         cocos2dx QQ群:280818155

====================== 相互学习,共同进步 ===================

转载请注明出处:http://blog.csdn.net/dingxiaowei2013/article/details/16853973

欢迎关注我的微博:http://weibo.com/u/2590571922
















本文转蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366211,如需转载请自行联系原作者

相关文章
|
4月前
|
Python
python socket 简单通信
python socket 简单通信
50 1
|
4月前
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
291 0
|
1月前
|
Kubernetes 网络协议 Python
Python网络编程:从Socket到Web应用
在信息时代,网络编程是软件开发的重要组成部分。Python作为多用途编程语言,提供了从Socket编程到Web应用开发的强大支持。本文将从基础的Socket编程入手,逐步深入到复杂的Web应用开发,涵盖Flask、Django等框架的应用,以及异步Web编程和微服务架构。通过本文,读者将全面了解Python在网络编程领域的应用。
37 1
|
2月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
3月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
3月前
|
SQL 开发框架 安全
Web开发中常见的安全缺陷及解决办法
Web开发中常见的安全缺陷及解决办法
|
5月前
|
前端开发 Python
前后端分离的进化:Python Web项目中的WebSocket实时通信解决方案
【7月更文挑战第18天】在Python的Flask框架中,结合Flask-SocketIO库可轻松实现WebSocket实时通信,促进前后端分离项目中的高效交互。示例展示了一个简单的聊天应用:Flask路由渲染HTML,客户端通过Socket.IO库连接服务器,发送消息并监听广播。此方法支持多种实时通信协议,适应不同环境,提供流畅的实时体验。
110 3
|
4月前
|
开发框架 .NET API
.Net Core Console 项目如何使用 HttpClient 与 Web 服务通信
.Net Core Console 项目如何使用 HttpClient 与 Web 服务通信
|
5月前
|
JavaScript 前端开发 UED
WebSocket在Python Web开发中的革新应用:解锁实时通信的新可能
【7月更文挑战第16天】WebSocket是实现Web实时通信的协议,与HTTP不同,它提供持久双向连接,允许服务器主动推送数据。Python有多种库如websockets和Flask-SocketIO支持WebSocket开发。使用Flask-SocketIO的简单示例包括定义路由、监听消息事件,并在HTML中用JavaScript建立连接。WebSocket提高了实时性、减少了服务器压力,广泛应用于聊天、游戏等场景。
69 1
|
5月前
|
移动开发 前端开发 网络协议
Python Web实时通信新纪元:基于WebSocket的前后端分离技术探索
【7月更文挑战第16天】WebSocket增强Web实时性,Python借助Flask-SocketIO简化实现。安装`flask`和`flask-socketio`,示例展示服务器端接收连接及消息并广播响应,前端HTML用Socket.IO库连接并监听事件。WebSocket开启双向通信新时代,助力动态Web应用开发。
66 1