最近做了一個項目,主要是給Unity3D和實時數據庫做通訊接口。雖然方案一直在變:從開始的UDP通訊變為TCP通訊,然后再變化為UDP通訊;然后通訊的對象又發生改變,由與數據庫的驅動進行通訊(主動推送數據給驅動,數據庫中數據發生變化把數據以UDP報文形式發送客戶端)改為與實時數據庫進行直接通訊(自己發送報文修改數據庫中的數據,自己請求需要獲取的數據并接收自己請求的數據);現在這個項目基本完結,由于這個過程既接觸到了UDP又接觸到了TCP,現在對其進行一番總結。
閱讀目錄
TCP與UDP都是網絡SOCKET通信協議,其最大的區別在于UDP是一種不可靠的網絡通訊服務,而TCP是一種可靠的網絡通信服務。眾所周知,TCP通過三次握手來實現網絡通訊的,這一機制保證了校驗數據,保證了可靠性;而UDP是不用創建鏈路把報文發送出去即可,它會根據ip地址自尋目的地,如果這個過程出現了問題就會把數據丟掉,但是UDP的傳輸速率比較高,反應速度較快。兩種傳輸方式各有利弊,要視具體的需求來選擇不同的通信協議了。
回到頂部在C#中已經提供了比較成熟的TCP通訊相關的類庫以及方法。因為要獲取數據庫中的實時數據,所以處理思路就是,在程序開始的時候開啟一個線程,對服務器端的數據進行接收,把接收到的數據做相應的處理;如果需要修改數據,那么就提供一個接口,對服務器端的數據庫中的數據進行修改,具體代碼如下:

1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.IO; 5 using System.Net; 6 using System.Net.Sockets; 7 using System.Text; 8 using System.Threading; 9 using System.Web; 10 11 namespace Rdbclass 12 { 13 public class Rdb 14 { 15 ArrayList arrDatalist = new ArrayList();//存儲需要發送的數據 16 ArrayList arrSendDataList = new ArrayList();//存儲改變了值的數據 17 18 PRivate TcpClient client;//聲明TCP客戶端 19 private ThreadStart threadStart;//聲明一個線程 20 private Thread client_th; 21 private string sip; 22 private int iPort; 23 //構造函數進行數據的初始化 24 public Rdb(string strip, ArrayList list, int Port) 25 { 26 arrDatalist = list; 27 sip = strip; 28 iPort = Port; 29 connect_s(); 30 } 31 32 //連接服務器 33 private void connect_s() 34 { 35 try 36 { 37 client = new TcpClient(sip, iPort); 38 threadStart = new ThreadStart(AcceptMsg); 39 client_th = new Thread(threadStart); 40 client_th.Start(); 41 } 42 catch (System.Exception ex) 43 { 44 throw new Exception(ex.ToString()); 45 } 46 } 47 //接收數據方法,在程序運行的時候開啟一個線程進行數據的接收 48 private void AcceptMsg() 49 { 50 NetworkStream ns = client.GetStream(); 51 //字組處理 52 while (true) 53 { 54 try 55 { 56 byte[] bytes = new byte[4096]; 57 byte[] sendBytes = new byte[4096]; 58 NetworkStream sendStream1 = client.GetStream(); 59 int bytesread = ns.Read(bytes, 0, bytes.Length); 60 string msg = Encoding.UTF8.GetString(bytes, 0, bytesread); 61 for (int i = 0; i < arrDatalist.Count; i++) 62 { 63 string strItemData = (string)arrDatalist[i]; 64 string[] Data = strItemData.Split('|'); 65 string[] DataReceive = msg.Split('|'); 66 67 if (Data[0].ToString() == DataReceive[1].ToString() && DataReceive[0].ToString() == "val") 68 { 69 arrDatalist.RemoveAt(i); 70 string strNewData = DataReceive[1] + "|" + DataReceive[2]; 71 arrDatalist.Add(strNewData); 72 sendBytes = Encoding.UTF8.GetBytes("ret|" + DataReceive[1] + "|ok!"); 73 sendStream1.Write(sendBytes, 0, sendBytes.Length); 74 sendStream1.Flush(); 75 } 76 } 77 ns.Flush(); 78 } 79 80 catch (System.Exception ex) 81 { 82 throw new Exception(ex.ToString()); 83 } 84 } 85 } 86 87 private void Sendmessage() 88 { 89 if (client == null) 90 return; 91 NetworkStream sendStream = client.GetStream(); 92 Byte[] sendBytes; 93 if (arrSendDataList.Count > 0) 94 { 95 for (int i = 0; i < arrSendDataList.Count; i++) 96 { 97 string message = arrSendDataList[i].ToString(); 98 arrSendDataList.RemoveAt(i); 99 sendBytes = Encoding.UTF8.GetBytes(message);100 sendStream.Write(sendBytes, 0, sendBytes.Length);101 sendStream.Flush();102 }103 }104 } 105 106 //修改原始數據里面的值并發送數據107 public void ModiData(string strName, string value)108 {109 try110 {111 int iCount = arrDatalist.Count;112 if (iCount > 0)113 {114 for (int i = 0; i < iCount; i++)115 {116 string strItemData = (string) arrDatalist[i];117 string[] Data = strItemData.Split('|');118 if (Data[0].ToString() == strName)119 {120 arrDatalist.RemoveAt(i);121 string strNewData = Data[0] + "|" + value;122 arrDatalist.Add(strNewData);123 arrSendDataList.Add("val|" + strNewData);124 break;125 }126 }127 Sendmessage();128 }129 }130 catch (Exception ex)131 {132 throw new Exception(ex.ToString());133 }134 }135 //退出整個應用136 public void Exit()137 {138 if (client != null)139 {140 client.Close();141 }142 }143 }144 }View Code回到頂部UDP通訊中,服務器端不會主動的去推送數據到客戶端,那么就需要客戶端定時輪詢服務器端的數據了。思路是先發送請求數據,然后讓此線程休眠100ms接收服務器端返回過來的請求數據,其具體代碼如下:

1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.IO; 5 using System.Net; 6 using System.Net.Sockets; 7 using System.Text; 8 using System.Threading; 9 10 namespace RdbUDP 11 { 12 public class UPDRdc 13 { 14 ArrayList arrDatalist = new ArrayList();//存儲點表的數據 15 ArrayList arrSendDataList = new ArrayList();//存儲改變了的值的數據 16 private string strSendIP ;//需要發送數據的地址 17 private int ISendport ; //發送的端口號 18 IPEndPoint remoteSendIpep; 19 ArrayList arrSendlist = new ArrayList(); 20 21 //11094 22 /// <summary> 23 /// 用于UDP發送的網絡服務類 24 /// </summary> 25 private UdpClient udpcSend; 26 27 28 public UPDRdc(ArrayList list, string SendIP, int SendPort) 29 { 30 arrDatalist = list; 31 strSendIP = SendIP; 32 ISendport = SendPort; 33 StartRecvData();//初始化接收數據 34 } 35 36 //初始化發送節點 37 private void SetSendPoint() 38
新聞熱點
疑難解答