C# Sending .wav file using WebSocket returns OperationAborted

So I have a local Node.js server and a C# client inside a Unity project, what I am trying to do is to stream a .wav file to the server in the same machine (localhost:3000) using WebSockets but the error I get is a pretty vague OperationAborted error, it doesn’t tell me if there is a type mismatch between the client and server or other thing I need to get fixed.

I’m new to web sockets so thank you in advance.

C# Client

public class WebSocketController : MonoBehaviour
{
	[SerializeField] private AudioSource microphoneSource;

	private void Start()
	{
		string url = "ws://localhost";
		int port = 3000;
		string filePath = "C:/Users/eduar/AppData/LocalLow/Richard J/Sound Recorder/Audio_2023_04_05_23_47_56_2845.wav";
		const int HEADER_SIZE = 44;
		byte[] requestBytes = ConvertWAVtoByteArray(filePath, microphoneSource, HEADER_SIZE);
		SendHttpRequest(url, filePath, port, requestBytes);
	}

	public string SendHttpRequest(string url, string filePath, int port, byte[] requestBytes)
	{
		string _responseMessage = null;
		Socket _socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

		using (_socket)
		{
			// Create and try to connect a dual-stack socket.
			try
			{
				// Create and connect a dual-stack socket.
				Debug.Log("Connecting to server.");
				_socket.Connect(new Uri(url).Host, port);
			}
			catch (SocketException e)
			{
				Debug.LogError("Could not connect to server: " + e.Message);
			}

			// Create the preBuffer data.
			byte[] preBuf = requestBytes;

			// Create the postBuffer data.
			byte[] postBuf = requestBytes;

			// Try to send the request.
			try
			{
				//Send file to the remote device.
				Debug.Log($"Sending {filePath} with buffers to the host.");

				SocketAsyncEventArgs _socketArgs = new SocketAsyncEventArgs();
				_socketArgs.SetBuffer(requestBytes, 0, requestBytes.Length);
				_socketArgs.Completed += new EventHandler<SocketAsyncEventArgs>(SendCallback);
				_socket.SendAsync(_socketArgs);
			}
			catch (SocketException e)
			{
				Debug.LogError("Could not send http request: " + e.Message + "

");
}
finally
{
// Release the socket.
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
}

		Debug.Log("Http response: " + _responseMessage);
		return _responseMessage;
	}

	private void SendCallback(object sender, SocketAsyncEventArgs e)
	{
		if (e.SocketError == SocketError.Success)
		{
			// To stream ou may need to specify some type of state and pass it into the SendHttpRequest method so you don't start sending from scratch again untill whole file is sent
			Debug.Log("Socket could send file sucessfully.");
		}
		else
		{
			Debug.LogError("Socket error: " + e.SocketError);
		}
	}

	private byte[] ConvertWAVtoByteArray(string filePath, AudioSource audioSource, int headerSize)
	{
		//Open the stream and read it back.
		byte[] bytes = new byte[audioSource.clip.samples + headerSize];
		using (FileStream fs = File.OpenRead(filePath))
		{
			fs.Read(bytes, 0, bytes.Length);
		}
		return bytes;
	}
}

JavaScript Server

const express = require('express');
const fs = require('fs')
const path = require('path')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server,{maxHttpBufferSize: 1e7})

io.on('connection', function (socket) {
  console.log("headers at connection:")
  console.log(socket.handshake.headers)
  socket.on('audio', async function (msg) {
      console.log("headers on evnt:")
      console.log(socket.handshake.headers)
      var date = new Date(msg.timeMillis);
      await fs.promises.writeFile(path.join(__dirname, "videos", `${date.toString()}.wav`), msg.data, "binary");         
  });
});

server.listen(3000)
console.log("Running on port: "+3000)

What you’re doing here is not at all a WebSocket communication. All you do is opening a TCP sockets and just blast your data towards your server. What you use here is NOT a websocket on the client side. Establishing a websocket connection involves an initial HTTP elevation handshake and each actual websocket packet has to follow the websocket protocol. Nothing of that is implemented in your client code. So your server most likely just closes the connection.

You may be able to use the ClientWebSocket class, though I’m not sure it’s actually supported in Unity. Also note that this class would not work in a WebGL build since it’s built on top of a normal TCP socket which are not supported in a WebGL build. Though I guess your client actually isn’t a WebGL build, since in WebGL you don’t have direct file access either.

While the web socket protocol isn’t too complicated, implementing it “manually” can get quite involved. I actually wrote a WebSocket server on top of an ordinary TCP stream in C#. It’s usually simply to use an existing solution like this one I just found by google.

Is there a reason you want to use a WebSocket? A bit more background what you actually want to do would help. Also WebSockets are based on messages. So you may want to re-evaluate your choices here.

Thanks Bunny83 so far. I changed my client code to use GitHub - endel/NativeWebSocket: 🔌 WebSocket client for Unity - with no external dependencies (WebGL, Native, Android, iOS, UWP) since ClientWebSocket Class from .Net isn’t working with Unity. I’m getting the Unable to connect to the remote server error now.

To contextualize this is a mobile game where I will record the player microphone and stream send to a server that will store it in wav. format until is being recorded.

C# Client

using UnityEngine;
using NativeWebSocket;

namespace DevPenguin.Utilities
{
    public class WebSocketController : MonoBehaviour
    {
        WebSocket websocket;

        // Start is called before the first frame update
        async void Start()
        {
            websocket = new WebSocket("ws://localhost:3000");

            websocket.OnOpen += () =>
            {
                Debug.Log("Connection open!");
            };

            websocket.OnError += (e) =>
            {
                Debug.Log("Error! " + e);
            };

            websocket.OnClose += (e) =>
            {
                Debug.Log("Connection closed!");
            };

            websocket.OnMessage += (bytes) =>
            {
                Debug.Log("OnMessage!");
                Debug.Log(bytes);
            };

            // Keep sending messages at every 0.3s
            InvokeRepeating("SendWebSocketMessage", 0.0f, 0.3f);

            // waiting for messages
            await websocket.Connect();
        }

        void Update()
        {
#if !UNITY_WEBGL || UNITY_EDITOR
            websocket.DispatchMessageQueue();
#endif
        }

        async void SendWebSocketMessage()
        {
            if (websocket.State == WebSocketState.Open)
            {
                // Sending bytes
                await websocket.Send(new byte[] { 10, 20, 30 });

                // Sending plain text
                await websocket.SendText("plain text message");
            }
        }

        private async void OnApplicationQuit()
        {
            await websocket.Close();
        }
    }
}