Search code examples
c#websocket.net-coredisposeunsafe

How can i fill a byte array with a string without creating a new array?


I am trying to open multiple websockets and i need somehow to either use the same buffers per socket or clear them before sending/receiving new messages. The receive method is good since i can pass a parameter of byte array and it will fill that one up without creating a new byte array instance.

What can i do with the BitConverter.GetBytes method?Do i need to start using an unsafe context and use overloaded GetBytes with pointer argument?Is there another way? I need it to fill the outBytes variable which i will define in the constructor.

public class Client:IDisposable
{
    //Fields
    public char[] innerData { get; private set; }

    private byte[] inBytes;
    private byte[] outBytes;

    private ArraySegment<byte> inSegment;
    private ArraySegment<byte> outSegment;


    private WebSocket webSocket;
    public WebSocket Socket => this.webSocket;

    public readonly string clientID;
    //Auxiliary
    private const int BufferSize = 1024;

    public static Client CreateClient(WebSocket socket, string id)
    {
        Client client = new Client(socket, id);

        return client;
    }

    public Client(WebSocket socket, string id)
    {
        this.inBytes = new byte[BufferSize];
        this.inSegment = new ArraySegment<byte>(inBytes);

        this.outBytes = new byte[BufferSize];
        this.outSegment = new ArraySegment<byte>(outBytes);


        this.webSocket = socket;
        this.clientID = id;
        this.innerData = new char[BufferSize];
    }
    public  async Task<WebSocketReceiveResult> ReceiveResult()
    {
        if(this.webSocket.State!=WebSocketState.Open)
        {
            return null;
        }

        WebSocketReceiveResult result = await this.webSocket.ReceiveAsync(this.inSegment, CancellationToken.None);
        Encoding.UTF8.GetChars(this.inSegment.Array, 0, BufferSize, this.innerData, 0);
        return result;
    }

    public async Task SendMessage(string message)
    {
        if(this.webSocket.State==WebSocketState.Open)
        {

            this.outBytes = Encoding.UTF8.GetBytes(message, 0, message.Length); //How can i fill the already existing outBytes?
            await this.webSocket.SendAsync(this.outSegment, WebSocketMessageType.Text, true, CancellationToken.None);
        }

    }

    public void Dispose()
    {
        if(this.webSocket.State!=WebSocketState.Closed)
        {
            this.webSocket.Dispose();
            this.webSocket = null;
        }
    }


}

I need to somehow use the already existing outBytes when i convert message that i will send.At the moment outBytes behaves like a pointer and every at every iteration of SendMessage method GetBytes will spawn a new byte array.


Solution

  • You apparently have a wrong misunderstanding of how GetBytes works, it does not generate a new array everytime, this overload :

    Encoding.GetBytes Method (String, Int32, Int32, Byte[], Int32)

    will

    encodes a set of characters from the specified string into the specified byte array (From MSDN)

    So your line should be

    Encoding.UTF8.GetBytes(message, 0, message.Length, this.outBytes, 0);
    

    That function will fill up your array with this string converted into bytes using UTF8 encoding... And you can use the return value, which is an integer, to check how many bytes have been written into the array.