[Unity3d]socket通信 切换到web版本时报错SecurityException解决办法
2013-12-04 00:10
555 查看
今天苦战了一天,就跟一个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
?
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:
[csharp]
view plain
copy
print
?
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端:
[csharp]
view plain
copy
print
?
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
具体错误如下:
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
?
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:
[csharp]
view plain
copy
?
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端:
[csharp]
view plain
copy
?
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
相关文章推荐
- [Unity3d]socket通信 切换到web版本时报错SecurityException解决办法
- Unity3d socket通信 切换到web版本时报错SecurityException解决办法
- Unity3D游戏,TCP,WEBCOSKT,HTTP通信架构 weaving-socket
- Web实时通信Socket.IO兼容浏览器版本IE7&IE8&IE9&IE10
- Spring WebSocket+SockJS+Stomp实现一对一、一对多通信
- socket通信之四:多线程版本的客户/服务器模型
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- unity3D中使用Socket进行数据通信(一)
- Unity3d使用Socket与java服务器通信
- 解决swift实现的websocket与后台通信问题:websocket is disconnected: masked and rev data is not currently supported
- ANDROID WebSocket+STOMP 1.0版本
- Socket通信-web服务器基本原理(静态)
- Socket,TCP,UDP,HTTP基本通信原理和OC版本Demo
- 利用flash与.net下socket通信实现WEB页面的“推”(一)基本概述
- Unity3D Web Socket Security! Unable to connect, as no valid crossdomain policy was found.
- 版本V1.0:基于socket通信的rpc
- QT:用QWebSocket实现webchannel,实现C++与HTML通信
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- websocket+php实现前后端实时通信
- 利用Flash作为桥梁连接WEB页面和服务器端Socket通信,达到服务器主动"推"客户端的效果