Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    WebSocket usage in C++

    Cinema 4D SDK
    c++ windows macos s24
    2
    6
    406
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      Cankar001
      last edited by

      Hi, i've spent quite some time now, setting up a websocket server in my plugin. The documentation unfortunately doesn't have many usage examples of the network.framework. Here is my current code that should setup and start the websocket correctly:
      Unbenannt.PNG
      The instance of this class is global in the plugin main file and gets deleted when the

      PluginEnd
      

      function is called. The problem that I currently have is this line:

      mWebSocketServer.ObservableConnected(true).AddObserver(
          [](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<void>
          {
              return maxon::OK;
          }, nullptr);
      

      This code does not compile, as the lambda can not be converted to maxon::ObserverObjectInterface*. But the docs here: https://developers.maxon.net/docs/cpp/2025_1_0/page_maxonapi_observers_usage.html state that Observers can take in lambdas and according to the header file the parameters of the lambda should be correct?

      About some hints into the right direction I would be very happy 🙂

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by m_adam

        Hi @Cankar001 we do not really have any official example for the Websocket, but fortunately I did make the Visual Studio Code Bridge project, which have the duty to exchange code from VSCode to Cinema via Websocket, and it's open source. So it is not nicely documented and explained as an example could be but it can serve you as a base.
        So find this example in Cinema-4D-Legacy-Visual-Studio-Code-Bridge-Plugin and look at the websocket_json_codeexchange.h and cpp.

        The main entry point is in WebSocketJsonCodeExchangeImpl::Start where all the observable are properly feed.

        Three special notes:

        • The code was written for S26 and is now directly merged into Cinema 4D, so it is not up to date, so for the observable the new way is to call it like that:
        g_wsServer.ObservableHandshake(true).AddObserver(OnHandShake) iferr_return;
        g_wsServer.ObservableConnected(true).AddObserver(OnConnected) iferr_return;
        g_wsServer.ObservableDisconnected(true).AddObserver(OnDisconnected) iferr_return;
        g_wsServer.ObservableMessage(true).AddObserver(OnMessage) iferr_return;
        
        • ObservableHandshake observable always need to be defined otherwise you won't be able to connect. Even if it's empty (like mine in OnHandShake).
        • You need to close all connections before calling StopWebServer otherwise it will wait forever. This means you needs to keep tracks of all theses connections somehow. In my case I do it by storing connections in a BaseArray during the OnConnect within the WebSocketJsonCodeExchangeImpl which is as a Singleton (so only one instance of it exist).

        Regarding your question it does not compile because you are calling it wrongly if I may say. First you pass a nullptr argument at the end that is not needed and secondly you do not handle the error that AddObserver emit which is probably the cause of the non-compilation. I would advice you to read Maxon API - Error Handling. With that's said here the adapted version that compile:

        g_wsServer.ObservableConnected(true).AddObserver(
        	[](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<void>
        	{
        		iferr_scope;
        		return maxon::OK;
        	}) iferr_return;
        

        If you need more help and there is detail you have hard time to understand in the code example do not hesitate to ask questions.
        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • C
          Cankar001
          last edited by

          Thank you so much @m_adam! I will take a deeper look into it and come back if I have any questions, also very good to see that there is a json parser as well already, as I was also planning to send json strings over the web socket 🙂

          1 Reply Last reply Reply Quote 0
          • C
            Cankar001
            last edited by Cankar001

            Hi @m_adam,

            thank you again for the code suggestions, I got it compiling and running now, but now I do have a runtime failure, I am trying to test the websocket connection with postman, and I get a 500 error, the logs of Cinema 4D say this:

            <net.maxon.datatype.internedid> net.maxon.http.type : <uint32> 1
            <net.maxon.datatype.internedid> net.maxon.http.file : <net.maxon.interface.string-C> index.html
            <net.maxon.interface.string-C> sec-websocket-extensions : <net.maxon.interface.string-C> permessage-deflate; client_max_window_bits
            <net.maxon.interface.string-C> sec-websocket-version : <net.maxon.interface.string-C> 13
            <net.maxon.interface.string-C> sec-websocket-key : <net.maxon.interface.string-C> j+y86BlBpKXcFzGDp/BOXg==
            <net.maxon.interface.string-C> host : <net.maxon.interface.string-C> localhost:19923
            <net.maxon.datatype.internedid> net.maxon.http.connection : <net.maxon.interface.string-C> Upgrade
            <net.maxon.interface.string-C> upgrade : <net.maxon.interface.string-C> websocket
            protocol not found
            Connection: Stopped with error httpcode [network_websocket_base_impl.cpp(556)] 
              Cause: websocket protocol not found [network_websocket_base_impl.cpp(646)].
            httpcode [network_websocket_base_impl.cpp(556)] 
              Cause: websocket protocol not found [network_websocket_base_impl.cpp(646)]
            

            This is my current websocket implementation:

            	WebSocket::WebSocket(int port)
            		: mPort(port)
            	{
            	}
            
            	WebSocket::~WebSocket()
            	{
            		maxon::Result<void> res = mWebSocketServer.StopWebServer();
            		if (res.GetErrorPointer() != nullptr)
            		{
            			ApplicationOutput("Failed to shutdown the websocket!");
            		}
            	}
            
            	maxon::Result<void> WebSocket::Start()
            	{
            		iferr_scope;
            
            		maxon::NetworkIpAddrPort addr(127, 0, 0, 1, mPort);
            		mWebSocketServer = maxon::NetworkWebSocketServerClass().Create() iferr_return;
            
            		WebSocket* instance = this;
            		mWebSocketServer.ObservableConnected(true).AddObserver(
            			[instance](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<void>
            			{
            				return instance->OnConnected(webSocket, request);
            			}) iferr_return;
            
            		mWebSocketServer.ObservableDisconnected(true).AddObserver(
            			[instance](const maxon::NetworkWebSocketConnectionRef& webSocket) -> void
            			{
            				instance->OnDisconnected(webSocket);
            			}) iferr_return;
            
            		mWebSocketServer.ObservableHandshake(true).AddObserver(
            			[instance](const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request) -> maxon::Result<String>
            			{
            				return instance->OnHandShake(webSocket, request);
            			}) iferr_return;
            
            		mWebSocketServer.ObservableMessage(true).AddObserver(
            			[instance](const maxon::NetworkWebSocketConnectionRef& webSocket, maxon::WEBSOCKET_OPCODE opCode, const maxon::BaseArray<Char>& data) -> maxon::Result<void>
            			{
            				return instance->OnMessage(webSocket, opCode, data);
            			}) iferr_return;
            
            		mWebSocketServer.StartWebServer(addr, false, "<tried different values here but no change>"_s) iferr_return;
            
            		return maxon::OK;
            	}
            
            	maxon::Result<void> WebSocket::OnConnected(const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request)
            	{
            		iferr_scope;
            
            		return maxon::OK;
            	}
            
            	void WebSocket::OnDisconnected(const maxon::NetworkWebSocketConnectionRef& webSocket)
            	{
            		iferr_scope_handler
            		{
            			return;
            		};
            	}
            
            	maxon::Result<String> WebSocket::OnHandShake(const maxon::NetworkWebSocketConnectionRef& webSocket, const maxon::DataDictionary& request)
            	{
            		iferr_scope;
            		return ""_s;
            	}
            
            	maxon::Result<void> WebSocket::OnMessage(const maxon::NetworkWebSocketConnectionRef& webSocket, maxon::WEBSOCKET_OPCODE opCode, const maxon::BaseArray<Char>& data)
            	{
            		iferr_scope;
            
            		return maxon::OK;
            	}
            

            Do you know, what could cause this error? Thank you very much for your help already!

            1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by m_adam

              Hi I do not have access to PostMan so it's hard to reproduce. Would be nice if you can provide a Python/C++/Javascript code that act as a client. So take my answers with a grain of salt.
              In my example I used a VsCode plugin (so a NodeJS instance), you can have a look at the client implementation
              Cinema-4D-Visual-Studio-Code-Extension
              .

              With that's said looking at the error I would say your request header should contain the protocol in the Sec-WebSocket-Protocol fields which should match the one you defined in mWebSocketServer.StartWebServer(addr, false, "<tried different values here but no change>"_s) iferr_return;.
              While Sec-WebSocket-Protocol is normally not a mandatory field, in our implementation it is mandatory to provide one.

              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              1 Reply Last reply Reply Quote 0
              • C
                Cankar001
                last edited by Cankar001

                Hi @m_adam, following your typescript example it worked now to connect! Thank you very much for your help 🙂

                Merry Christmas and a Happy New Year!

                1 Reply Last reply Reply Quote 1
                • First post
                  Last post