什么企業(yè)適合做網(wǎng)站北京seo經(jīng)理
兄弟們,我來填坑了,o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o,前幾天寫了個tcp模擬websocket客戶端的以為完成,后面需要發(fā)送消息給服務(wù)端,以為簡單不就是一個發(fā)送消息么,這不是一下的事情,諾 sslStrem.Write(bt,0,bt.length);這不就是么,結(jié)果結(jié)果啪啪啪打臉,臉都要腫了o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o。
錯誤信息:“xeaThe client frame was not masked but all client frames must be masked” 后面查找資料發(fā)現(xiàn)需要按照websocket協(xié)議來發(fā)送websocket結(jié)構(gòu)體的消息幀。
如下圖
WebSocket 消息幀結(jié)構(gòu)
??? FIN(1位): 表示是否是最后一幀。
??? RSV1, RSV2, RSV3(各1位): 保留位,通常為 0。
??? Opcode(4位): 幀的類型(例如:文本幀、二進(jìn)制幀、關(guān)閉幀等)。
??? Mask(1位): 表示負(fù)載是否被掩碼。
??? Payload length(7/7+16/7+64位): 表示負(fù)載數(shù)據(jù)的長度。
??? Masking key(32位): 如果 Mask 為 1,則存在掩碼鍵。
??? Payload data: 實際傳輸?shù)臄?shù)據(jù)。
找了一大堆資料結(jié)果還是沒成功,一想到有開源的websocket開源代碼里面肯定是有發(fā)送消息的方法。得按照這個思路在websocket-sharp開源里找到了,然后在里面看啊看游啊游,頭都要大了,最后還是仿寫了一套相對簡單的,后面一試成功了不容易啊。
代碼如下:
public void Send2(string data){byte[] bytes = Encoding.UTF8.GetBytes(data);Stream sourceStream = new MemoryStream(bytes);try{var len = sourceStream.Length;if (len == 0){bool sent3 = send2(0x1, 0x1, new byte[0], false);return;}var quo = len / 1016;var rem = (int)(len % 1016);byte[] buff = null;if (quo == 0){buff = new byte[rem];bool sent2 = sourceStream.Read(buff, 0, rem) == rem && send2(0x1, 0x1, buff, false);return;}if (quo == 1 && rem == 0){buff = new byte[1016];bool sent2 = sourceStream.Read(buff, 0, 1016) == 1016 && send2(0x1, 0x1, buff, false);return;}/* Send fragments */// Beginbuff = new byte[1016];var sent = sourceStream.Read(buff, 0, 1016) == 1016 && send2(0x0, 0x1, buff, false);if (!sent)return;// Continuevar n = rem == 0 ? quo - 2 : quo - 1;for (long i = 0; i < n; i++){sent = sourceStream.Read(buff, 0, 1016) == 1016 && send2(0x0, 0x0, buff, false);if (!sent)return;}// Endif (rem == 0)rem = 1016;elsebuff = new byte[rem];sent = sourceStream.Read(buff, 0, rem) == rem && send2(0x1, 0x0, buff, false);return;}catch{}finally{sourceStream.Dispose();}}private bool send2(byte fin, byte opcode, byte[] data, bool compressed){byte _payloadLength;byte _rsv1;byte _rsv2;byte _rsv3;byte[] _extPayloadLength;byte[] _maskingKey;byte _mask;//PayloadData _payloadData = new PayloadData(data);_rsv1 = compressed ? (byte)0x1 : (byte)0x0;_rsv2 = 0x0;_rsv3 = 0x0;var len = data.Length;if (len < 126){_payloadLength = (byte)len;_extPayloadLength = new byte[0];}else if (len < 0x010000){_payloadLength = (byte)126;var ret = BitConverter.GetBytes((ushort)len);Array.Reverse(ret);_extPayloadLength = ret;//_extPayloadLength = ((ushort)len).ToByteArray(ByteOrder.Big);}else{_payloadLength = (byte)127;var ret = BitConverter.GetBytes((ulong)len);Array.Reverse(ret);_extPayloadLength = ret;//_extPayloadLength = ((ulong)len).ToByteArray(ByteOrder.Big);}if (true){_mask = 0x1;var key = new byte[4];RNGCryptoServiceProvider RandomNumber = new RNGCryptoServiceProvider();RandomNumber.GetBytes(key);_maskingKey = key;for (long i = 0; i < data.Length; i++){data[i] = (byte)(data[i] ^ key[i % 4]);}}using (var buff = new MemoryStream()){var header = (int)fin;header = (header << 1) + (int)_rsv1;header = (header << 1) + (int)_rsv2;header = (header << 1) + (int)_rsv3;header = (header << 4) + (int)opcode;header = (header << 1) + (int)_mask;header = (header << 7) + (int)_payloadLength;var uint16Header = (ushort)header;var ret = BitConverter.GetBytes(uint16Header);Array.Reverse(ret);var rawHeader = ret;buff.Write(rawHeader, 0, 2);if (_payloadLength >= 126)buff.Write(_extPayloadLength, 0, _extPayloadLength.Length);if (_mask == 0x1)buff.Write(_maskingKey, 0, 4);if (_payloadLength > 0){var bytes = data;if (_payloadLength > 126){using (var src = new MemoryStream(bytes))src.CopyTo(buff, 1024);}elsebuff.Write(bytes, 0, bytes.Length);}buff.Close();var rawFrame = buff.ToArray();try{sslStream.Write(rawFrame, 0, rawFrame.Length);}catch{return false;}return true;}}
https://download.csdn.net/download/qq_35319925/90187478https://download.csdn.net/download/qq_35319925/90187478 上面提供了代碼鏈接下載地址。獲取電腦本地的音頻設(shè)備并實時傳輸音頻數(shù)據(jù)到后臺。這個demo是可以跑通的。方便大家使用