小記:針對目前功能越來越強大的智能手機來說,在PC端支持對手機中的用戶數據作同步、備份以及恢復等保護措施的應用已經急需完善。不僅要對數據作保護,而且用戶更希望自己的手機跟PC能夠一體化,以及和遠程服務器的一體化。用戶希望在手機端的操作能夠轉移到PC端,對於PC端大屏幕的電腦來說,完成同樣的操作可以大量的節省用戶的時間。對於功能強大的手機來說,有近1/2的應用可以在PC端同步。所以對PC端應用的規划要以系統的角度來對待。同時要保證手機端和PC端的主流交互模式應保持一致。個人觀點:數據的一體化和管理的多元化是以后發展的一個趨勢。下面進行今天的學習,今天的實驗室移動端和PC端的數據交互及解析。
1,如何實現移動端和PC端的數據交互?
答:1,藍牙 2,NFC技術 3,紅外 4,Socket.
NFC和藍牙的異同點:
相同點:都是近距離傳輸。
不同點: NFC優於紅外和藍牙傳輸方式。作為一種面向消費者的交易機制,NFC比紅外更快、更可靠而且簡單得多,不用向紅外那樣必須嚴格的對齊才能傳輸數據。與藍牙相比,NFC面向近距離交易,適用於交換財務信息或敏感的個人信息等重要數據;藍牙能夠彌補NFC通信距離不足的缺點,適用於較長距離數據通信。因此,NFC和藍牙互為補充,共同存在。事實上,快捷輕型的NFC 協議可以用於引導兩台設備之間的藍牙配對過程,促進了藍牙的使用。但是要實現遠距離的數據傳輸那就只能用Socket了,
下面進行代碼的分析:
首先在PC上建立服務端Server.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net; using System.Net.Sockets; using System.Threading; namespace TcpServer { class Program { public static Socket serverSocket; static Thread threadSend; static Thread sendDataToClient; static int count = 1; static void Main(string[] args) { //確定端口號 int port = 121; //設定連接IP string host = "192.168.1.100"; //將IP地址字符串轉化為IP地址實例 IPAddress ip = IPAddress.Parse(host); //將網絡端點表示為 IP 地址和端口號 IPEndPoint ipe = new IPEndPoint(ip, port); //建立Socket //addressFamily 參數指定 Socket 類使用的尋址方案 //socketType 參數指定 Socket 類的類型 //protocolType 參數指定 Socket 使用的協議。 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //socket與本地終結點建立關聯 socket.Bind(ipe); while (true) { //開始監聽端口 socket.Listen(0); Console.WriteLine("服務已開啟,請等待....." + DateTime.Now.ToString() + DateTime.Now.Millisecond.ToString()); //為新建的連接建立新的Socket目的為客戶端將要建立連接 serverSocket = socket.Accept(); Console.WriteLine("連接已建立......" + DateTime.Now.ToString() + DateTime.Now.Millisecond.ToString()); Console.WriteLine("客戶端IP:"+serverSocket.RemoteEndPoint); string recStr =string.Empty; //定義緩沖區用於接收客戶端的數據 byte[] recbyte = new byte[1024]; ReceiveData(); sendDataToClient = new Thread(sendData); sendDataToClient.Start(); } } public static void sendData() { while (true) { Console.WriteLine("send to client\n"); //服務端給客戶端回送消息 string strSend = "Hello Android Client!" + DateTime.Now.Second; //string strSend = "HelloClient1HelloClient2HelloClient3HelloClient4HelloClient5HelloClient6HelloClient7HelloClient8HelloClient9HelloClient10HelloClient11HelloClien12HelloClien13HelloClien14HelloClien15HelloClient16"; byte[] sendByte = new byte[1024]; //將發送的字符串轉換為byte[] sendByte = UTF8Encoding.UTF8.GetBytes(strSend); //服務端發送數據 serverSocket.Send(sendByte, sendByte.Length, 0); Thread.Sleep(1000); } } #region /// <summary> /// 異步連接 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> /// <param name="clientSocket"></param> public static void Connect(IPAddress ip, int port) { serverSocket.BeginConnect(ip, port, new AsyncCallback(ConnectCallback), serverSocket); } private static void ConnectCallback(IAsyncResult ar) { try { Socket handler = (Socket)ar.AsyncState; handler.EndConnect(ar); } catch (SocketException ex) { throw ex; } } /// <summary> /// 發送數據 /// </summary> /// <param name="data"></param> public static void Send(string data) { //Send(System.Text.Encoding.UTF8.GetBytes(data)); Send(UTF8Encoding.UTF8.GetBytes(data)); } /// <summary> /// 發送數據 /// </summary> /// <param name="byteData"></param> private static void Send(byte[] byteData) { try { int length = byteData.Length; byte[] head = BitConverter.GetBytes(length); byte[] data = new byte[head.Length + byteData.Length]; Array.Copy(head, data, head.Length); Array.Copy(byteData, 0, data, head.Length, byteData.Length); serverSocket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), serverSocket); } catch (SocketException ex) { } } private static void SendCallback(IAsyncResult ar) { try { Socket handler = (Socket)ar.AsyncState; handler.EndSend(ar); } catch (SocketException ex) { throw ex; } } static byte[] MsgBuffer = new byte[128]; /// <summary> /// 接收消息 /// </summary> public static void ReceiveData() { if (serverSocket.ReceiveBufferSize > 0) { serverSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); } } private static void ReceiveCallback(IAsyncResult ar) { try { int REnd = serverSocket.EndReceive(ar); Console.WriteLine("長度:" + REnd); if (REnd > 0) { byte[] data = new byte[REnd]; Array.Copy(MsgBuffer, 0, data, 0, REnd); int Msglen = data.Length; //在此次可以對data進行按需處理 serverSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); //Console.WriteLine("接收服務端的信息:{0}", Encoding.ASCII.GetString(MsgBuffer, 0, Msglen)); Console.WriteLine("接收服務端的信息:{0}", UTF8Encoding.UTF8.GetString(data, 0, Msglen)); } else { dispose(); } } catch (SocketException ex) { } } private static void dispose() { try { serverSocket.Shutdown(SocketShutdown.Both); serverSocket.Close(); } catch (Exception ex) { throw ex; } } #endregion } }
移動端使用Unity3D寫的腳本掛在mainCamera上,代碼如下:
using UnityEngine; using System.Collections; using System.Net.Sockets; using System.Net; using System; using System.Text; using System.IO; public class client : MonoBehaviour { public GUIText text; public GUIText path; public static Socket clientSocket; // Use this for initialization void Start () { //服務器IP string LocalIP = "192.168.1.100";
//端口號 int port = 121; IPAddress ip =IPAddress.Parse(LocalIP); IPEndPoint ipe = new IPEndPoint(ip,port); clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立客戶端Socket clientSocket.Connect(ipe);
StartCoroutine("sendData"); //啟動協同程序 StartCoroutine("getInfo"); } // Update is called once per frame void Update () { if(Input.GetKey(KeyCode.Escape)||Input.GetKey(KeyCode.Home)) { Application.Quit(); } } void OnGUI() { if(GUI.Button(new Rect(Screen.width/2-40,30,100,60),"截圖")) { StartCoroutine("GetCapture"); } } IEnumerator GetCapture () { yield return new WaitForEndOfFrame(); int width = Screen.width; int height = Screen.height; Texture2D tex = new Texture2D (width, height, TextureFormat.RGB24, false); tex.ReadPixels (new Rect (0, 0, width, height), 0, 0, true); byte[] imagebytes = tex.EncodeToPNG ();//轉化為png圖 tex.Compress (false);//對屏幕緩存進行壓縮 //image.mainTexture = tex;//對屏幕緩存進行顯示(縮略圖) string PicPath="storage"; File.WriteAllBytes (Application.persistentDataPath+"/"+Time.time+ ".png", imagebytes);//存儲png圖 path.text = Application.persistentDataPath+"/"; } /// <summary> /// 向服務器發送消息 /// </summary> /// <returns>The data.</returns> public IEnumerator sendData() { int i=0; while(true) { string sendStr = i.ToString()+"你好 server,I am Android"; byte[] sendBytes = UTF8Encoding.UTF8.GetBytes(sendStr); clientSocket.Send(sendBytes); i++; yield return new WaitForSeconds(1f); } } /// <summary> /// 得到服務器回應 /// </summary> /// <returns>The info.</returns> public IEnumerator getInfo() { while(true) { byte[] revBytes = new byte[1024]; int bytes = clientSocket.Receive(revBytes, revBytes.Length, 0); string revStr =""; //revStr += Encoding.ASCII.GetString(revBytes, 0, bytes); revStr += UTF8Encoding.UTF8.GetString(revBytes,0,bytes); Debug.Log ("接收到服務器消息:"+revStr); text.text = "From Server:"+revStr; yield return null; } } }
服務器端運行結果:
服務器回送消息代碼:string strSend = "Hello Android Client!" + DateTime.Now.Second;
局域網下測試沒有什么問題,以后無論是做應用還是網絡游戲肯定少不了的是Socket網絡數據傳輸,多了解點網絡知識還是很有必要的尤其是TCP協議,如有錯誤,歡迎指正。