Handling stream socket errors in UWP c++winRT

Kenneth Gilpin 0 Reputation points
2023-09-14T10:07:06.24+00:00

hello,

I've tried to adapt the microsoft example streamsocket app.

I can get the connect working and pass information back and forth, but can't work out how to handle errors. The only examples I can find are in c#. In this code snippet:

//.h
bool connected{ false };
bool closing { false };
Windows::Networking::Sockets::StreamSocket m_streamSocket;
Windows::Networking::HostName hostName{ L"192.168.86.48" };
Windows::Foundation::IAsyncAction OpenSocket();

//.cpp
using namespace Windows::Networking::Sockets;

Windows::Foundation::IAsyncAction MainPage::OpenSocket() {

    if (connected) {
      return;
    }

    try
    {
        co_await m_streamSocket.ConnectAsync(hostName, L"1337");
        connected = true;
    }
    catch (winrt::hresult_error const& ex)
    {
        OutputDebugStringW(L"catch");
        SocketErrorStatus errorStatus = SocketError::GetStatus(ex.to_abi());


        if (errorStatus == SocketErrorStatus::ConnectionTimedOut) 
        {
            connected = false;
            OutputDebugStringW(L"ConnectionTimedOut");
    }
        SocketErrorStatus webErrorStatus{ SocketError::GetStatus(ex.to_abi()) };
        auto msg = (webErrorStatus != SocketErrorStatus::Unknown) ? winrt::to_hstring((int32_t)webErrorStatus) :winrt::to_hstring(ex.to_abi());

    std::wstringstream str;
    str \<\< L"webErrorStatus: " \<\< msg;
    ::OutputDebugString(str.str().c_str());

        closing = true;
    	//no dispose in c++winrt?
    	m_streamSocket = nullptr;
    }

}

The connection works as expected when I open the host. When I don't and allow the connection to time out the app crashes with:

Exception thrown at 0x00007FFDBE624C3C (KernelBase.dll) in Monitor1.exe: WinRT originate error - 0x8007274C : 'A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.'.

I can't catch the error before the crash. In the above code the catch block never executes. "catch" and "ConnectionTimedOut" never print to the output. I can't find any c++winRT networking code samples online that handle errors. I suspect the try..catch is not catching them somehow...

I've tried stackoverflow but have got nowhere. Can anyone help. I'd dearly love help with the error handling. Ideally it would be great for a fully functioning c++winrt socket example like we have for c#

kenneth

Universal Windows Platform (UWP)
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,732 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Kenneth Gilpin 0 Reputation points
    2023-09-16T22:18:22.7933333+00:00

    Thank you @Viorel , that works. When visual studio intercepted the error (thought it was a fatal exception) I ticked the dialog in the alert window as you said and it doesn't 'crash' any more. Here's the working code:

    //.xaml
    <ListBox x:Name="clientListBox">
    
    //.h
    bool connected{ false };
    bool closing { false };
    Windows::Networking::Sockets::StreamSocket m_streamSocket;
    hstring socketAddress = L"1337";
    Windows::Networking::HostName hostName{ L"192.168.86.48" };
    Windows::Foundation::IAsyncAction OpenSocket();
    
    //.cpp
    using namespace Windows::Networking::Sockets;
    
    Windows::Foundation::IAsyncAction MainPage::OpenSocket() {
    
        if (connected) {
    		clientListBox().Items().Append(winrt::box_value(L"already connected"));
    		return;
        }
    
        try
        {
    		clientListBox().Items().Append(winrt::box_value(L"client is trying to connect..."));
    		co_await m_streamSocket.ConnectAsync(hostName, socketAddress);
    		connected = true;
    		clientListBox().Items().Append(winrt::box_value(L"client connected"));
        }
    	catch (winrt::hresult_error const& ex)
    	{ 
    		SocketErrorStatus errorStatus = SocketError::GetStatus(ex.to_abi());
    		connected = false;
    		closing = true;
    		//no dispose in c++winrt?
    		m_streamSocket = nullptr;
    	
    		std::wstringstream wstringstream;
    		//full list here: https://learn.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketerrorstatus  			
    
    		if (errorStatus == SocketErrorStatus::ConnectionTimedOut) {
    			clientListBox().Items().Append(winrt::box_value(L"Computer at - " + hostName.RawName() + L": " + socketAddress + L" timed out.\nCheck it is trying to connect."));
    			wstringstream << L"A connection attempt failed.";
    			::OutputDebugString(wstringstream.str().c_str());
    		}
    
    		else if (errorStatus == SocketErrorStatus::ConnectionRefused) {
    			//WinRT originate error - 0x8007274D : 'No connection could be made because the target machine actively refused it.'.
    			clientListBox().Items().Append(winrt::box_value(L"Other computer refused connection - \nCheck IP: " + hostName.RawName() + L"\nCheck socket: " + socketAddress));
    			wstringstream << L"Connection actively refused.\n";
    			::OutputDebugString(wstringstream.str().c_str());
    		}
    
    		else {
    			auto msg = (errorStatus != SocketErrorStatus::Unknown) ? winrt::to_hstring((int32_t)errorStatus) : winrt::to_hstring(ex.to_abi());
    			wstringstream << L"webErrorStatus: " << msg;
    			::OutputDebugString(wstringstream.str().c_str());
    		}
    
    	}
    }
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.