How can i send a message from my WinForm VB.NET project to my WebSocket?
Actually i was able to do it by sending proper byte data to the NetworkStream in c# via the following code in c# which codify the string message to byte array:
private static byte[] EncodeMessageToSend(string message)
{
byte[] response;
byte[] bytesRaw = Encoding.UTF8.GetBytes(message);
byte[] frame = new byte[10];
int indexStartRawData = -1;
int length = bytesRaw.Length;
frame[0] = (Byte)129;
if (length <= 125)
{
frame[1] = (Byte)length;
indexStartRawData = 2;
}
else if (length >= 126 && length <= 65535)
{
frame[1] = (Byte)126;
frame[2] = (Byte)((length >> 8) & 255);
frame[3] = (Byte)(length & 255);
indexStartRawData = 4;
}
else
{
frame[1] = (Byte)127;
frame[2] = (Byte)((length >> 56) & 255);
frame[3] = (Byte)((length >> 48) & 255);
frame[4] = (Byte)((length >> 40) & 255);
frame[5] = (Byte)((length >> 32) & 255);
frame[6] = (Byte)((length >> 24) & 255);
frame[7] = (Byte)((length >> 16) & 255);
frame[8] = (Byte)((length >> 8) & 255);
frame[9] = (Byte)(length & 255);
indexStartRawData = 10;
}
response = new Byte[indexStartRawData + length];
Int32 i, reponseIdx = 0;
//Add the frame bytes to the reponse
for (i = 0; i < indexStartRawData; i++)
{
response[reponseIdx] = frame[i];
reponseIdx++;
}
//Add the data bytes to the response
for (i = 0; i < length; i++)
{
response[reponseIdx] = bytesRaw[i];
reponseIdx++;
}
return response;
}
Then i jsut used that code with stream.Write but what will be an equivalent code in VB? or is there another way to send a message to the WebSocket?
PS: the websocket doesn't accept a simple string or a simple string converted to byte[] i've yet tryed it.
I send a message over a websocket by using System.Net.Websockets.Websocket which has an asynchronous send function:
Dim bytes = Encoding.UTF8.GetBytes(message)
Await socket.SendAsync(New ArraySegment(Of Byte)(bytes, 0, bytes.length), Websockets.WebsocketMessageType.Text, True, cancelToken)
Note that chunking may be required depending on the maximum frame size; if so, send each chunk but the last with the penultimate parameter as False and adjust the initial position and length of the array segment accordingly.
(Addendum: I've just noticed that the initial position and segment length are not required in the ArraySegment(Of Byte) construction if making it out of the whole array, but I'm going to leave it in place here because it will be clearer what changes would need to be made to chunk the message.)
Related
I have one byte of data and from there I have to extract it in the following manner.
data[0] has to extract
id(5 bit)
Sequence(2 bit)
HashAppData(1 bit)
data[1] has to extract
id(6 bit)
offset(2 bit)
Required functions are below where byte array length is 2 and I have to extract to the above manner.
public static int ParseData(byte[] data)
{
// All code goes here
}
Couldn't find any suitable solution to how do I make it. Can you please extract it?
EDIT: Fragment datatype should be in Integer
Something like this?
int id = (data[0] >> 3) & 31;
int sequence = (data[0] >> 1) & 3;
int hashAppData = data[0] & 1;
int id2 = (data[1] >> 2) & 63;
int offset = data[1] & 3;
This is how I'd do it for the first byte:
byte value = 155;
byte maskForHighest5 = 128+64+32+16+8;
byte maskForNext2 = 4+2;
byte maskForLast = 1;
byte result1 = (byte)((value & maskForHighest5) >> 3); // shift right 3 bits
byte result2 = (byte)((value & maskForNext2) >> 1); // shift right 1 bit
byte result3 = (byte)(value & maskForLast);
Working demo (.NET Fiddle):
https://dotnetfiddle.net/lNZ9TR
Code for the 2nd byte will be very similar.
If you're uncomfortable with bit manipulation, use an extension method to keep the intent of ParseData clear. This extension can be adapted for other integers by replacing both uses of byte with the necessary type.
public static int GetBitValue(this byte b, int offset, int length)
{
const int ByteWidth = sizeof(byte) * 8;
// System.Diagnostics validation - Excluded in release builds
Debug.Assert(offset >= 0);
Debug.Assert(offset < ByteWidth);
Debug.Assert(length > 0);
Debug.Assert(length <= ByteWidth);
Debug.Assert(offset + length <= ByteWidth);
var shift = ByteWidth - offset - length;
var mask = (1 << length) - 1;
return (b >> shift) & mask;
}
Usage in this case:
public static int ParseData(byte[] data)
{
{ // data[0]
var id = data[0].GetBitValue(0, 5);
var sequence = data[0].GetBitValue(5, 2);
var hashAppData = data[0].GetBitValue(7, 1);
}
{ // data[1]
var id = data[1].GetBitValue(0, 6);
var offset = data[1].GetBitValue(6, 2);
}
// ... return necessary data
}
I'm working in a project where I need to stream microphone in Unity (2018.4.19f1) over the network using RTP. I've already found some examples of using Microphone class class but all of them are meant to record the audio to a file or to reproduce it using AudioClip. Right now I'm creating the microphone using the following code:
mic = Microphone.Start(null, true, 1, 44100); // Mono
Then After I have the following logic in the Update() loop:
private void Update()
{
if ((pos = Microphone.GetPosition(null)) > 0)
{
if (lastPos > pos) lastPos = 0;
if (pos - lastPos > 0)
{
int len = (pos - lastPos) * mic.channels;
float[] samples = new float[len];
mic.GetData(samples, lastPos);
//TODO: process samples
lastPos = pos;
}
}
}
I would like to know what's the audio format stored in samples and if it's possible to encode this audio and send it over RTP for example in unity. I would like to avoid using 3rd party assets whenever possible.
After some investigations finally I managed to implement a working script that basically captures the RAW PCM audio from the Microphone and stream it over RTP/UDP. RTP headers are populated by some hard-coded values, so probably you should adapt the code to your needs. Remember to add an "AudioSource" component to your gameobject.
To test the reception you can just go and use ffmpeg player (ffplay), for example:
ffplay rtp://0.0.0.0:your_port
Following is the C# script:
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
public static class RtpPacket
{
public static void WriteHeader(byte[] rtpPacket
, int rtpVersion
, int rtpPadding
, int rtpExtension
, int rtpSrcCount
, int rtpMarker
, int rtpPayload)
{
rtpPacket[0] = (byte)((rtpVersion << 6) | (rtpPadding << 5) | (rtpExtension << 4) | rtpSrcCount);
rtpPacket[1] = (byte)((rtpMarker << 7) | (rtpPayload & 0x7F));
}
public static void WriteSequenceNumber(byte[] rtpPacket, uint emptySeqId)
{
rtpPacket[2] = ((byte)((emptySeqId >> 8) & 0xFF));
rtpPacket[3] = ((byte)((emptySeqId >> 0) & 0xFF));
}
public static void WriteTS(byte[] rtpPacket, uint ts)
{
rtpPacket[4] = ((byte)((ts >> 24) & 0xFF));
rtpPacket[5] = ((byte)((ts >> 16) & 0xFF));
rtpPacket[6] = ((byte)((ts >> 8) & 0xFF));
rtpPacket[7] = ((byte)((ts >> 0) & 0xFF));
}
public static void WriteSSRC(byte[] rtpPacket, uint ssrc)
{
rtpPacket[8] = ((byte)((ssrc >> 24) & 0xFF));
rtpPacket[9] = ((byte)((ssrc >> 16) & 0xFF));
rtpPacket[10] = ((byte)((ssrc >> 8) & 0xFF));
rtpPacket[11] = ((byte)((ssrc >> 0) & 0xFF));
}
}
public class AudioStreamer : MonoBehaviour
{
// Audio control variables
AudioClip mic;
int lastPos, pos;
// UDP Socket variables
private Socket socket;
private IPEndPoint RemoteEndPoint;
private UInt32 sequenecId = 0;
void SetRtpHeader(byte[] rtpPacket)
{
// Populate RTP Packet Header
// 0 - Version, P, X, CC, M, PT and Sequence Number
// 32 - Timestamp. H264 uses a 90kHz clock
// 64 - SSRC
// 96 - CSRCs (optional)
// nn - Extension ID and Length
// nn - Extension header
RtpPacket.WriteHeader(rtpPacket
, 2 // version
, 0 // padding
, 0 // extension
, 0 // csrc_count
, 1 // marker, set to one for last packet
, 11); // payload_type PCM 16bits BE signed
RtpPacket.WriteSequenceNumber(rtpPacket, sequenecId);
RtpPacket.WriteTS(rtpPacket, Convert.ToUInt32(DateTime.Now.Millisecond * 90));
RtpPacket.WriteSSRC(rtpPacket, 0);
sequenecId++;
}
void SendToServer(float[] samples)
{
const int RTP_HEADER_LEN = 12;
if (socket == null) return;
if (samples == null || samples.Length == 0) return;
// Convert audio from float to signed 16 bit PCM BigEndian and copy it to the byte array
var byteArray = new byte[samples.Length * sizeof(Int16)]; // to convert each sample float to Int16
int i = 0;
int j = 0;
while (i < samples.Length)
{
Int16 sample = Convert.ToInt16((samples[i] * Int16.MaxValue) / 100);
byteArray[j] = (byte)(sample & 0xFF);
byteArray[j + 1] = (byte)((sample >> 8) & 0xFF);
i = i + 1;
j = j + 2;
}
var dataToSend = byteArray.Length;
int maxEthMTU = 1400;
int offset = 0;
while (dataToSend > 0)
{
var bodyLen = Math.Min(dataToSend, maxEthMTU);
var rtpAudioData = new byte[RTP_HEADER_LEN + bodyLen];
SetRtpHeader(rtpAudioData);
System.Array.Copy(byteArray, offset, rtpAudioData, RTP_HEADER_LEN, bodyLen);
int dataSent = socket.SendTo(rtpAudioData, 0, rtpAudioData.Length, SocketFlags.None, RemoteEndPoint);
dataToSend = dataToSend - dataSent;
offset = offset + dataSent;
}
}
void Start()
{
RemoteEndPoint = new IPEndPoint(IPAddress.Parse("your_server_ip"), your_server_port);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
mic = Microphone.Start(null, true, 1, 44100); // Mono
}
private void Update()
{
if ((pos = Microphone.GetPosition(null)) > 0)
{
if (lastPos > pos) lastPos = 0;
if (pos - lastPos > 0)
{
// Allocate the space for the new sample.
int len = (pos - lastPos) * mic.channels;
float[] samples = new float[len];
mic.GetData(samples, lastPos);
SendToServer(samples);
lastPos = pos;
}
}
}
void OnDestroy()
{
Microphone.End(null);
}
}
Good afternoon everyone. Faced a problem: it is necessary to read data from the devices using the modbus protocol. I can not understand how to get a response from the device.
So I call my function, but how do I get data from the device? Maybe someone can help.
P.S. Please, do not advise using ready-made libraries like nmodbus - with them I did everything, I want to try it myself. Thank you.
static void Main(string[] args)
{
var serial = new SerialPort("COM6", 19200);
serial.Handshake = Handshake.None;
serial.Parity = Parity.None;
serial.DataBits = 8;
serial.StopBits = StopBits.One;
serial.Open();
serial.Write(ReadHoldingRegister(2, 1024, 16), 0, 8);
serial.Close();
Console.ReadLine();
}
#region Function 3
public static byte[] ReadHoldingRegister(int id, int startAddress, int length)
{
byte[] data = new byte[8];
byte High, Low;
data[0] = Convert.ToByte(id);
data[1] = Convert.ToByte(3);
byte[] _adr = BitConverter.GetBytes(startAddress - 1);
data[2] = _adr[1];
data[3] = _adr[0];
byte[] _length = BitConverter.GetBytes(length);
data[4] = _length[1];
data[5] = _length[0];
myCRC(data, 6, out High, out Low);
data[6] = Low;
data[7] = High;
return data;
}
#endregion
#region CRC
public static void myCRC(byte[] message, int length, out byte CRCHigh, out byte CRCLow)
{
ushort CRCFull = 0xFFFF;
for (int i = 0; i < length; i++)
{
CRCFull = (ushort)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
if ((CRCFull & 0x0001) == 0)
CRCFull = (ushort)(CRCFull >> 1);
else
{
CRCFull = (ushort)((CRCFull >> 1) ^ 0xA001);
}
}
}
CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRCLow = (byte)(CRCFull & 0xFF);
}
#endregion
}
Processing a response is not "simple", you really need to account for errors, inter character and inter packet timing, etc. It should also probably be on a separate high-priority thread. The Modbus specs have some processing state diagrams that illustrate what (at a minimum) should be done. However, as a VERY SIMPLE, brute force, polling EXAMPLE, you could start with something like this:
static Queue<byte> GetResponse(SerialPort serial, int timeoutMSecs)
{
Queue<byte> response = new Queue<byte>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds < timeoutMSecs)
{
if (serial.BytesToRead == 0) continue; // Nothing received, continue waiting
response.Enqueue((byte)serial.ReadByte()); // Add rx byte to queue
stopwatch.Reset(); // Reset timeout
if (response.Count > 255) break; // Maximum RTU packet?
}
return response;
}
In your main function
static void Main(string[] args)
{
...
serial.DiscardInBuffer(); // Clear any remaining rx bytes
serial.Write(ReadHoldingRegister(2, 1024, 16), 0, 8);
Queue<byte> response = GetResponse(serial, 5);
if (response.Count > 0)
{
// Process Response
// 1) check the CRC
// 2) if crc ok, check if it is an exception response
// 3) if not an exception check that it "matches" the request
// ...
}
...
}
I have an array of audio data, which is a lot of Int32 numbers represented by array of bytes (each 4 byte element represents an Int32) and i want to do some manipulation on the data (for example, add 10 to each Int32).
I converted the bytes to Int32, do the manipulation and convert it back to bytes as in this example:
//byte[] buffer;
for (int i=0; i<buffer.Length; i+=4)
{
Int32 temp0 = BitConverter.ToInt32(buffer, i);
temp0 += 10;
byte[] temp1 = BitConverter.GetBytes(temp0);
for (int j=0;j<4;j++)
{
buffer[i + j] = temp1[j];
}
}
But I would like to know if there is a better way to do such manipulation.
You can check the .NET Reference Source for pointers (grin) on how to convert from/to big endian.
class intFromBigEndianByteArray {
public byte[] b;
public int this[int i] {
get {
i <<= 2; // i *= 4; // optional
return (int)b[i] << 24 | (int)b[i + 1] << 16 | (int)b[i + 2] << 8 | b[i + 3];
}
set {
i <<= 2; // i *= 4; // optional
b[i ] = (byte)(value >> 24);
b[i + 1] = (byte)(value >> 16);
b[i + 2] = (byte)(value >> 8);
b[i + 3] = (byte)value;
}
}
}
and sample use:
byte[] buffer = { 127, 255, 255, 255, 255, 255, 255, 255 };//big endian { int.MaxValue, -1 }
//bool check = BitConverter.IsLittleEndian; // true
//int test = BitConverter.ToInt32(buffer, 0); // -129 (incorrect because little endian)
var fakeIntBuffer = new intFromBigEndianByteArray() { b = buffer };
fakeIntBuffer[0] += 2; // { 128, 0, 0, 1 } = big endian int.MinValue - 1
fakeIntBuffer[1] += 2; // { 0, 0, 0, 1 } = big endian 1
Debug.Print(string.Join(", ", buffer)); // "128, 0, 0, 0, 1, 0, 0, 1"
For better performance you can look into parallel processing and SIMD instructions - Using SSE in C#
For even better performance, you can look into Utilizing the GPU with c#
How about the following approach:
struct My
{
public int Int;
}
var bytes = Enumerable.Range(0, 20).Select(n => (byte)(n + 240)).ToArray();
foreach (var b in bytes) Console.Write("{0,-4}", b);
// Pin the managed memory
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
for (int i = 0; i < bytes.Length; i += 4)
{
// Copy the data
My my = (My)Marshal.PtrToStructure<My>(handle.AddrOfPinnedObject() + i);
my.Int += 10;
// Copy back
Marshal.StructureToPtr(my, handle.AddrOfPinnedObject() + i, true);
}
// Unpin
handle.Free();
foreach (var b in bytes) Console.Write("{0,-4}", b);
I made it just for fun.
Not sure that's less ugly.
I don't know, will it be faster? Test it.
I have a byte[] and I'm looking for the most efficient way to base64 encode it.
The problem is that the built in .Net method Convert.FromBase64CharArray requires a char[] as an input, and converting my byte[] to a char[] just to convert it again to a base64 encoded array seems pretty stupid.
Is there any more direct way to do it?
[[EDIT:]] I'll expaling what I want to acheive better - I have a byte[] and I need to return a new base64 encoded byte[]
Byte[] -> String:
use
system.convert.tobase64string
Convert.ToBase64String(byte[] data)
String -> Byte[]:
use
system.convert.frombase64string
Convert.FromBase64String(string data)
Base64 is a way to represent bytes in a textual form (as a string). So there is no such thing as a Base64 encoded byte[]. You'd have a base64 encoded string, which you could decode back to a byte[].
However, if you want to end up with a byte array, you could take the base64 encoded string and convert it to a byte array, like:
string base64String = Convert.ToBase64String(bytes);
byte[] stringBytes = Encoding.ASCII.GetBytes(base64String);
This, however, makes no sense because the best way to represent a byte[] as a byte[], is the byte[] itself :)
Here is the code to base64 encode directly to byte array (tested to be performing +-10% of .Net Implementation, but allocates half the memory):
static public void testBase64EncodeToBuffer()
{
for (int i = 1; i < 200; ++i)
{
// prep test data
byte[] testData = new byte[i];
for (int j = 0; j < i; ++j)
testData[j] = (byte)(j ^ i);
// test
testBase64(testData);
}
}
static void testBase64(byte[] data)
{
if (!appendBase64(data, 0, data.Length, false).SequenceEqual(System.Text.Encoding.ASCII.GetBytes(Convert.ToBase64String(data)))) throw new Exception("Base 64 encoding failed");
}
static public byte[] appendBase64(byte[] data
, int offset
, int size
, bool addLineBreaks = false)
{
byte[] buffer;
int bufferPos = 0;
int requiredSize = (4 * ((size + 2) / 3));
// size/76*2 for 2 line break characters
if (addLineBreaks) requiredSize += requiredSize + (requiredSize / 38);
buffer = new byte[requiredSize];
UInt32 octet_a;
UInt32 octet_b;
UInt32 octet_c;
UInt32 triple;
int lineCount = 0;
int sizeMod = size - (size % 3);
// adding all data triplets
for (; offset < sizeMod;)
{
octet_a = data[offset++];
octet_b = data[offset++];
octet_c = data[offset++];
triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
buffer[bufferPos++] = base64EncodingTable[(triple >> 3 * 6) & 0x3F];
buffer[bufferPos++] = base64EncodingTable[(triple >> 2 * 6) & 0x3F];
buffer[bufferPos++] = base64EncodingTable[(triple >> 1 * 6) & 0x3F];
buffer[bufferPos++] = base64EncodingTable[(triple >> 0 * 6) & 0x3F];
if (addLineBreaks)
{
if (++lineCount == 19)
{
buffer[bufferPos++] = 13;
buffer[bufferPos++] = 10;
lineCount = 0;
}
}
}
// last bytes
if (sizeMod < size)
{
octet_a = offset < size ? data[offset++] : (UInt32)0;
octet_b = offset < size ? data[offset++] : (UInt32)0;
octet_c = (UInt32)0; // last character is definitely padded
triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
buffer[bufferPos++] = base64EncodingTable[(triple >> 3 * 6) & 0x3F];
buffer[bufferPos++] = base64EncodingTable[(triple >> 2 * 6) & 0x3F];
buffer[bufferPos++] = base64EncodingTable[(triple >> 1 * 6) & 0x3F];
buffer[bufferPos++] = base64EncodingTable[(triple >> 0 * 6) & 0x3F];
// add padding '='
sizeMod = size % 3;
// last character is definitely padded
buffer[bufferPos - 1] = (byte)'=';
if (sizeMod == 1) buffer[bufferPos - 2] = (byte)'=';
}
return buffer;
}
byte[] base64EncodedStringBytes = Encoding.ASCII.GetBytes(Convert.ToBase64String(binaryData))
Based on your edit and comments.. would this be what you're after?
byte[] newByteArray = UTF8Encoding.UTF8.GetBytes(Convert.ToBase64String(currentByteArray));
You could use the String Convert.ToBase64String(byte[]) to encode the byte array into a base64 string, then Byte[] Convert.FromBase64String(string) to convert the resulting string back into a byte array.
To retrieve your image from byte to base64 string....
Model property:
public byte[] NomineePhoto { get; set; }
public string NomineePhoneInBase64Str
{
get {
if (NomineePhoto == null)
return "";
return $"data:image/png;base64,{Convert.ToBase64String(NomineePhoto)}";
}
}
IN view:
<img style="height:50px;width:50px" src="#item.NomineePhoneInBase64Str" />
import base64
encoded = base64.b64encode(b'[3.\x01#\xbcr\xa9/$\xc3\ xe1 "')
print(encoded)
data = base64.b64decode(encoded)
print(data)
This method is efficient irrespective of the characters. For reference I included space, Double Quotes too.
public void ProcessRequest(HttpContext context)
{
string constring = ConfigurationManager.ConnectionStrings["SQL_Connection_String"].ConnectionString;
SqlConnection conn = new SqlConnection(constring);
conn.Open();
SqlCommand cmd = new SqlCommand("select image1 from TestGo where TestId=1", conn);
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
MemoryStream str = new MemoryStream();
context.Response.Clear();
Byte[] bytes = (Byte[])dr[0];
string d = System.Text.Encoding.Default.GetString(bytes);
byte[] bytes2 = Convert.FromBase64String(d);
//context.Response.Write(d);
Image img = Image.FromStream(new MemoryStream(bytes2));
img.Save(context.Response.OutputStream, ImageFormat.Png);
context.Response.Flush();
str.WriteTo(context.Response.OutputStream);
str.Dispose();
str.Close();
conn.Close();
context.Response.End();
}