今天苦战了一天,就跟一个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,如需转载请自行联系原作者