一、框架
1.UDP框架 GCDAsyncUdpSocket腐宋;
2.加密方式,采用aes_cfb128 iv為0 ;
3.抓包驗證wireshark
二欺嗤、數(shù)據(jù)初始化
1.初始化UDPSocket
_castSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:_castQueue];
(1)開啟廣播 Broadcast卫枝;
if (![_castSocket enableBroadcast:YES error:&error]) {
UdpLog(@"enableBroadcast error:%@",error);
}
(2)接收數(shù)據(jù) beginReceiving;
if (![_castSocket beginReceiving:&error]) {
UdpLog(@"beginReceiving error:%@",error);
}
(3)指定端口 不指定則會隨機(jī)分配吆玖;
三马篮、數(shù)據(jù)發(fā)送
(1)發(fā)送地址
端口與設(shè)備端協(xié)商,這里以60000舉例
local:port -> 192.168.2.255 : 60000 + index
(2)數(shù)據(jù)
說明 | |
---|---|
dataByte | 總長度(1) + flag(1) + ssidLen(1) + pwdLen(1) + ssid + pwd + checkSum(2) |
ssid: | ssid為中文則采用utf-8編碼翅阵,其他則為ASCII編碼 |
pwd | pwd需要加密 |
checkSum | 校驗和 |
//判斷中文
- (BOOL)isChinese:(NSString *) str{
for(int i=0; i< [str length];i++){
int a = [str characterAtIndex:i];
if( a > 0x4E00 && a < 0x9FFF){
return YES;
}
}
return NO;
}
//aes加密
- (NSData *)gnAesEncryptData:(uint8_t *)crypt_data len:(int)crypt_len keyData:(NSData *)keydata{
unsigned char *keyResult=(Byte*)[keydata bytes];
AES_KEY aes_key;
unsigned char *outByte = NULL;
outByte = (unsigned char *)malloc(crypt_len+1);
memset(outByte, 0, crypt_len+1);
AES_set_encrypt_key(keyResult, 128, &aes_key);
int number = 0;
NSData *ivData = [NSData dataWithBytes:&number length:1];
unsigned char *ivResult = (Byte*)[ivData bytes];
NSData *numData = [NSData dataWithBytes:&number length:1];
int *numResult = (int *)[numData bytes];
AES_cfb128_encrypt(crypt_data,outByte,crypt_len, &aes_key,ivResult,numResult ,AES_ENCRYPT);
NSData *Decrydata = [NSData dataWithBytes:outByte length:crypt_len];
return Decrydata;
}
(3)發(fā)送結(jié)構(gòu)
利用廣播的數(shù)據(jù)長度length發(fā)送數(shù)據(jù) 每次發(fā)送11bit數(shù)據(jù)掷匠,
幀頭與設(shè)備端協(xié)商岖圈,這里以0x480舉例
數(shù)據(jù)分為
說明 | |
---|---|
幀頭 | 0x480 , 0x481,0x482,0x483… |
幀數(shù)據(jù) | index(4bit) + data(7bit) |
bit7 幀頭固定為1 蜂科,數(shù)據(jù)幀固定為0;
發(fā)送數(shù)按組發(fā)送 一組是一個幀頭*2 + 8個數(shù)據(jù)幀崇摄;
[self.castClient sendData:[self zeroDataWithCount:value] toHost:_broadcastIP port:60000+_sendCount];
(4)轉(zhuǎn)碼
由于bit7是幀頭位, 所以每次只能發(fā)送6bit數(shù)據(jù),就需要對整個數(shù)據(jù) 進(jìn)行8bit->6bit轉(zhuǎn)碼
例如
0x 11 22 (0b 0001 0001 0010 0010 (高位到低位)) -> 1000 1000 0100 0100(低位到高位)
-> 100010 000100 010000(低位到高位) -> 010001 001000 0000010(高位到低位) ->0x11 08 02
int bitCount = 6;
int dataLength = (int)data.length;
Byte codeData[dataLength * bitCount];
int outLength = (dataLength * 8 + bitCount - 1) /bitCount;
Byte outData[outLength];
Byte *dataByte = (Byte *)data.bytes;
for (int i = 0; i < dataLength; i ++) {
for (int j = 0; j < 8; j++) {
codeData[i * 8 + j] = (dataByte[i] >> j) & 0x01;
}
}
for (int i = 0; i < outLength; i++) {
outData[i] = 0;
for (int j = 0; j < bitCount; j ++) {
outData[i] |= codeData[i * bitCount + j] << j;
}
}
NSData *tempCodeData = [NSData dataWithBytes:outData length:sizeof(outData)];
return tempCodeData;
(5)傳輸規(guī)則
每包之間間隔20ms;間隔時間可按實際情況調(diào)整
(1) 幀頭*2 (0x480 -> 1152)
(2) 幀數(shù)據(jù) 8 (組序號<<7 + data[index])
(3) 幀頭2 (0x481 -> 1153)
(4) 幀數(shù)據(jù) 8
(5) 幀頭2 (0x482 -> 1154)
(6) 幀數(shù)據(jù) *8
...
截屏2021-04-29 15.49.01.png