最近做了一个项目,主要是给Unity3D和实时数据库做通讯接口。虽然方案一直在变:从开始的UDP通讯变为TCP通讯,然后再变化为UDP通讯;然后通讯的对象又发生改变,由与数据库的驱动进行通讯(主动推送数据给驱动,数据库中数据发生变化把数据以UDP报文形式发送客户端)改为与实时数据库进行直接通讯(自己发送报文修改数据库中的数据,自己请求需要获取的数据并接收自己请求的数据);现在这个项目基本完结,由于这个过程既接触到了UDP又接触到了TCP,现在对其进行一番总结。
阅读目录
- TCP通讯协议与UDP通讯协议的区别
- TCP通讯(用TCP协议对报文进行发送与接收)
- UDP通讯(用UDP协议对报文进行发送与接收)
- UDP协议实现一台PC机多客户端与服务端进行通讯
- UDP协议和TCP协议网络通讯的测试方法
- 总结
TCP与UDP都是网络SOCKET通信协议,其最大的区别在于UDP是一种不可靠的网络通讯服务,而TCP是一种可靠的网络通信服务。众所周知,TCP通过三次握手来实现网络通讯的,这一机制保证了校验数据,保证了可靠性;而UDP是不用创建链路把报文发送出去即可,它会根据IP地址自寻目的地,如果这个过程出现了问题就会把数据丢掉,但是UDP的传输速率比较高,反应速度较快。两种传输方式各有利弊,要视具体的需求来选择不同的通信协议了。
TCP通讯(用TCP协议对报文进行发送与接收)
在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 try 110 { 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 }