数据採集器服务——Socket(今天才发现AES加解密代码跟贴的时候不一样,貌似乱码,不知什么情况)...
近期剛做的一個(gè)項(xiàng)目。關(guān)于 Socket TCP 通信。
需求方提供了一個(gè) ARM 機(jī)器,及數(shù)據(jù)採集器,須要我做一個(gè)服務(wù)端與數(shù)據(jù)採集器進(jìn)行交互。
目的:
數(shù)據(jù)採集器:定時(shí)將讀取到的數(shù)據(jù)發(fā)送到服務(wù)端。
服務(wù)端:將數(shù)據(jù)採集器發(fā)送過來的數(shù)據(jù)保存在本地。
要求:
1、通信以 TCP 方式進(jìn)行交互,port可配置。
2、自己實(shí)現(xiàn)握手、心跳包機(jī)制。
3、TCP 包結(jié)構(gòu)包含:包頭、有效數(shù)據(jù)總長(zhǎng)度、有效數(shù)據(jù)、CRC 校驗(yàn)、包尾,當(dāng)中有效數(shù)據(jù)包含指令序號(hào)和指令內(nèi)容,為經(jīng)過 AES 128位加密的 XML 數(shù)據(jù)。
4、加密算法:AES 128位。加密模式:CBC。填充模式:NoPadding。
5、握手過程:(下面過程均以 TCP 包結(jié)構(gòu)加密形式傳輸,并僅僅提主要內(nèi)容數(shù)據(jù)。省略 CRC 校驗(yàn)說明)
(1)數(shù)據(jù)採集器發(fā)送請(qǐng)求包到服務(wù)端,服務(wù)端解析包結(jié)構(gòu)后取出數(shù)據(jù)段進(jìn)行 AES 解密。
(2)服務(wù)端推斷該包為請(qǐng)求包后回復(fù)一個(gè)包括一個(gè)隨機(jī)序列的包到數(shù)據(jù)採集器。
(3)數(shù)據(jù)採集器接收到包后將隨機(jī)序列與 MD5 密鑰組合后進(jìn)行 MD5 加密。并回發(fā)給服務(wù)端。
(4)服務(wù)端接收到加密后的內(nèi)容,并與本地加密后的內(nèi)容進(jìn)行比較,通過則回復(fù) pass,否則回復(fù) fail。
(5)數(shù)據(jù)採集器收到 pass 則握手成功并建立連接,否則握手失敗并斷開連接。
6、心跳包:握手建立后。採集器每隔一定時(shí)間會(huì)往服務(wù)端發(fā)送一個(gè)心跳包。服務(wù)端收到心跳包后應(yīng)馬上應(yīng)答。回復(fù)server當(dāng)前時(shí)間信息供採集器校時(shí)。
7、數(shù)據(jù)包:採集器在握手建立后。會(huì)定時(shí)向服務(wù)端發(fā)送斷點(diǎn)數(shù)據(jù)包和實(shí)時(shí)數(shù)據(jù)包,服務(wù)端接收到以后將數(shù)據(jù)保存在本地 PC 并回復(fù) pass。
1、創(chuàng)建服務(wù)端Socket
(C#)
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 36829); //本機(jī)預(yù)使用的IP和portSocket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);newsock.Bind(ipep); //綁定newsock.Listen(10); //監(jiān)聽(Node.js)
var server = net.createServer(function(socket) { //'connection' listenerconsole.log('client connected'); }); server.listen(36829, function() { //'listening' listenerconsole.log('server bound'); });2、創(chuàng)建client對(duì)象并監(jiān)聽
(C#)
(Node.js) var server = net.createServer(function(socket) { //'connection' listenerconsole.log('client connected');socket.on('end', function() {console.log('client disconnected');});socket.on('data', function(data){console.log(data.length);console.log(data);}); }); server.listen(36829, function() { //'listening' listenerconsole.log('server bound'); });
由于其它內(nèi)容涉及到保密性,所以以下僅僅貼一下 AES 加解密過程
// AES 解密 public static string AESDecrypt(byte[] data) {SymmetricAlgorithm aes = Rijndael.Create();aes.Key = keyArray; // 密鑰aes.IV = keyArray; // 向量aes.Mode = CipherMode.CBC;aes.Padding = PaddingMode.None;byte[] decryptBytes = new byte[data.Length];using (MemoryStream ms = new MemoryStream(data)){using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read)){cs.Read(decryptBytes, 0, decryptBytes.Length);cs.Close();ms.Close();}}aes.Clear();return System.Text.Encoding.Default.GetString(decryptBytes).Replace("\0", " "); }// AES 加密 public static byte[] AESEncrypt(byte[] data) {SymmetricAlgorithm aes = Rijndael.Create();aes.Key = keyArray;aes.IV = keyArray;aes.Mode = CipherMode.CBC;aes.Padding = PaddingMode.None;using (MemoryStream ms = new MemoryStream()){using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)){cs.Write(data, 0, data.Length);cs.FlushFinalBlock();byte[] cipherBytes = ms.ToArray(); // 得到加密后的字節(jié)數(shù)組cs.Close();ms.Close();aes.Clear();return cipherBytes;}} }
總結(jié)
以上是生活随笔為你收集整理的数据採集器服务——Socket(今天才发现AES加解密代码跟贴的时候不一样,貌似乱码,不知什么情况)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 3 递归调用与二分法
- 下一篇: 复习笔记——操作系统