locked
I need C++ sample for StreamSocket using

    Question

  • There is JS sample only in Metro samples. I cannot use it for C++
    Sunday, September 18, 2011 12:27 PM

Answers

  • Hi Arthur,

    Try this sample. You my see an intellisense error on the ref new AsyncActionCompletedHandler, but it compiles and ran as expected.

    //
    // MainPage.xaml.cpp
    // Implementation of the MainPage.xaml class.
    //
    
    #include "pch.h"
    #include "MainPage.xaml.h"
    
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Data;
    using namespace BlankCppTestApp;
    using namespace Windows::Networking::Sockets;
    using namespace Windows::Foundation;
    
    MainPage::MainPage()
    {
        InitializeComponent();
    }
    
    MainPage::~MainPage()
    {
    }
    
    void BlankCppTestApp::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
    	StreamSocket^ streamSocket = ref new StreamSocket();
    	
    	auto streamSocketConnectOperation = streamSocket->ConnectAsync(ref new Windows::Networking::HostName("remotehost"), "80", Windows::Networking::Sockets::SocketProtectionLevel::PlainSocket);
    
    	streamSocketConnectOperation->Completed = ref new AsyncActionCompletedHandler([=](IAsyncAction^ a)
           {
    		   a->Close();
           });
    
    	streamSocketConnectOperation->Start();
    }
    

    Thanks,

    -David

    Friday, September 30, 2011 11:32 PM
    Moderator

All replies

  • You are correct that there is only a JS version.  As a C++ developer you should be able to follow the JS code however and see how the APIs are used, then integrate this into your Metro C++ application.  If you have questions when implementing this, please post back here as it will surely help others!
    Jeff Sanders (MSFT)
    Monday, September 19, 2011 1:31 PM
    Moderator
  • However, the description of API finctions (ConnectAsync for example http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocket.connectasync(v=VS.85).aspx#Y0 ) are different for C++ and JS. Could you provide some sample in C++, please?
    Monday, September 19, 2011 2:38 PM
  • Hi Arthur,

    Try this sample. You my see an intellisense error on the ref new AsyncActionCompletedHandler, but it compiles and ran as expected.

    //
    // MainPage.xaml.cpp
    // Implementation of the MainPage.xaml class.
    //
    
    #include "pch.h"
    #include "MainPage.xaml.h"
    
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Data;
    using namespace BlankCppTestApp;
    using namespace Windows::Networking::Sockets;
    using namespace Windows::Foundation;
    
    MainPage::MainPage()
    {
        InitializeComponent();
    }
    
    MainPage::~MainPage()
    {
    }
    
    void BlankCppTestApp::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
    	StreamSocket^ streamSocket = ref new StreamSocket();
    	
    	auto streamSocketConnectOperation = streamSocket->ConnectAsync(ref new Windows::Networking::HostName("remotehost"), "80", Windows::Networking::Sockets::SocketProtectionLevel::PlainSocket);
    
    	streamSocketConnectOperation->Completed = ref new AsyncActionCompletedHandler([=](IAsyncAction^ a)
           {
    		   a->Close();
           });
    
    	streamSocketConnectOperation->Start();
    }
    

    Thanks,

    -David

    Friday, September 30, 2011 11:32 PM
    Moderator
  • Thank you so much.

    To say that "As a C++ developer you should be able to follow the JS code" is ridiculous. All the samples in JavaScript and the code available for C# depend on the "await" command. However, no such command exists in C++ and the way you handle ASYNC callbacks have completely different syntax. From a MSFT employee, that's just insulting.

    See here for more: http://msdn.microsoft.com/en-us/library/windows/apps/hh464924(v=vs.85).aspx#asynchronous_patterns_in__with_c__

    However, with zero samples of C++11 pre-beta handling Sockets proper, we're left to scrounge around for hours to find the most basic elements of the new syntax.

    Thanks David for pointing out that "IAsyncAction" was the elusive type required. It was very much appreciated.

    -rk

    Tuesday, October 04, 2011 9:32 PM
  • "Windows 8 Asynchrony with PPL and C++"

    http://blogs.msdn.com/b/nativeconcurrency/archive/2011/09/22/windows-8-asynchrony-with-ppl.aspx

    has an alternate approach too.

    Good luck.

    p.s.

    I don't really understand this yet, but you made me want to know why "IAsyncAction^" should be used.

    If I look at the definition of   "StreamSocketConnectOperation"

    http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocketconnectoperation(v=vs.85).aspx

    which is what is returned by   streamSocket->ConnectAsync( ... ),

    public ref class StreamSocketConnectOperation sealed : Object,
        IAsyncAction,
        IAsyncInfo

    p.p.s.  I second memeovore's comment.

    Tuesday, October 04, 2011 10:36 PM
  • Rick, check out some of C++ async stuff in the metro samples.  The ppl tasks and continuations greatly simplify chaining async code:

     

    StorageFolder^ documentsFolder = KnownFolders::DocumentsLibrary;
        task<StorageFile^> getFileTask(documentsFolder->GetFileAsync("sample.txt"));
        auto outputStream = std::make_shared<IOutputStream^>(nullptr);
        getFileTask.then([this](StorageFile^ storageFileSample) -> IAsyncOperation<IRandomAccessStream^>^ {
            // Get the returned file and attempt to open it for a read+write operation
            return storageFileSample->OpenAsync(FileAccessMode::ReadWrite);
        }).then([this, outputStream](IRandomAccessStream^ accessStream) -> IAsyncOperation<unsigned int>^ {
            *outputStream = accessStream->GetOutputStreamAt(0);
            DataWriter^ dataWriter = ref new DataWriter(*outputStream);
            dataWriter->WriteString(Scenario2Textbox->Text);
            return dataWriter->StoreAsync();
        }).then([outputStream](unsigned int) {
            return (*outputStream)->FlushAsync();
        }).then([this](bool){
            Scenario2Output_textblock->Text = "\"" + Scenario2Textbox->Text + "\" was written to sample.txt";
        });

     

    Wednesday, October 05, 2011 12:36 AM
  • Thanks Jeremiah, Both going the tasks/PPL route or the nested Async hander route, though, run into the same challenge for those of us trying to jump into C++ and the absolute lack of any socket samples or explicit documentation regarding the return types of the OperationActions out there in strongly typed C++. The difference between opening up an IOutputStream to read in a file is a bit different from keeping a StreamSocket ( or StreamSocketListener ) process open and accepting a very basic stream of client bytes.
    For example, the following code works for creating a very basic SocketListener and having it fire when a single client on the same network connects to it and wants to send a single Int32 value (for POC testing):
     
    Windows::Networking::Sockets::StreamSocketListener^ socketListener = ref new StreamSocketListener("192.168.1.76");
    socketListener->ServiceName = "8888";
    auto AcceptOperationSocketListener = socketListener->AcceptAsync();
    AcceptOperationSocketListener->Completed = ref new AsyncOperationCompletedHandler<Windows::Networking::Sockets::StreamSocket^>(
    		[page](IAsyncOperation<StreamSocket^> ^op)
    	{
    		if (op->Status == AsyncStatus::Completed) 
            { 
    			Windows::Networking::Sockets::StreamSocket^ stream = op->GetResults();
    
    			IInputStream^ inputStream = stream->InputStream;
    
    			auto opRead = inputStream->ReadAsync(<strong>UNKNOWN_1</strong>, 4, Windows::Storage::Streams::InputStreamOptions.None);
    			opRead->Completed = ref new AsyncOperationCompletedHandler<<strong>UNKNOWN_2</strong>^>(
    				[page](IAsyncOperation<<strong>UNKNOWN_3</strong>^> ^op)
    			{
    
    
    				// WHAT TYPES ARE REQUIRED IN THE THREE UNKNOWNS ABOVE (IF MY ASSUMPTION IS CORRECT?)
    
    				// THE FIRST PARAMETER OF inputStream->ReadAsync( is a buffer. But how is this accessed inside the LAMBDA expression?				
    
    				//WHAT DO ONCE I'M IN HERE TO ACCESS THOSE 4 BYTES FROM THE CLIENT? THE BUFFER OR THE ^op SOMEHOW?
    
    			});
    
    			opRead->Start();
    		}
    	});
    	AcceptOperationSocketListener->Start();
    
    
     
    Now if I do this with nested async handlers like above or I go the task route, they BOTH require me to know what the UNKNOWN types are above. Conceptually, it's the same. If you don't know what the return AcceptOperator is and how to manipulate it in the next step, you're dead in the water. But if those don't exist in any documentation and no sample's exist, we're left scrambling for hours trying to figure this out.
    Can anyone who knows C++11 PLEASE help out here? Take 5 minutes out and give us the most basic sample for a WebSocket or WebSocket Listener that actually receives something and actually does something with it. At this point, I'm just trying to get a single Int32 passed from the client to be read by the server. I'm not even tackling the while(true) { // continue to handle client messages } loop yet ( though if you can help there too, that would be much appreciate ;)
    That's where we're coming from. Thanks everyone for helping out. Many of us are totally jazzed up about C++ and don't mind the hard work, but right now, there is NOTHING out there on WebSockets for C++ using the new Async model, either nested or PPL/Tasks and the demos on single File or Image async loading isn't the same thing once you get past the initial GetAsync.
    Nested or Tasks using Sockets. Either would be perfect. At least one is desperately needed by the community.
    Thanks again,
    rk
    Wednesday, October 05, 2011 5:42 PM
  • The following code uses the nested Async operators to establish a StreamSocketListener, accept a connection and read the value. However, I still can't figure out how to wrap this in a while() loop or have the results re-reference themselves in order to handle multiple client requests.
    Does anyone know how to convert this single transaction code into a solution that will progressively accept multiple values from the client?
    Partial Solution:
    	MainPage^ page = this;
    	txtOut->Text = "LISTENING FOR CLIENT... ";	
    	Windows::Networking::Sockets::StreamSocketListener^ socketListener = ref new StreamSocketListener("192.168.1.76");
    	socketListener->ServiceName = "8888";
    	auto AcceptOperationSocketListener = socketListener->AcceptAsync();
    	AcceptOperationSocketListener->Completed = ref new AsyncOperationCompletedHandler<Windows::Networking::Sockets::StreamSocket^>(
    	[page](IAsyncOperation<StreamSocket^> ^op)
    	{
    		if (op->Status == AsyncStatus::Completed) 
            { 
    			page->txtOut->Text += "CLIENT ACCEPTED...";
    
    			Windows::Networking::Sockets::StreamSocket^ stream = op->GetResults();
    			IInputStream^ inputStream = stream->InputStream;
    			Windows::Storage::Streams::DataReader^ reader = ref new Windows::Storage::Streams::DataReader(inputStream);	
    			reader->InputStreamOptions = InputStreamOptions::Partial;
    
    			//HOW DO WE REPEAT THIS BLOCK TO READ IN MULTIPLE VALUES FROM THE CLIENT?
    			
    
    				Windows::Storage::Streams::DataReaderLoadOperation^ opRead = reader->LoadAsync(4);
    				opRead->Completed = ref new AsyncOperationCompletedHandler<unsigned int>(
    				[page, reader](IAsyncOperation<unsigned int> ^op)
    				{
    					int val = reader->ReadInt32();
    
    					// CONVERT VALUE TO STRING AND DISPLAY IT
    					std::wstringstream wss; 
    			        wss << val; 
    					page->txtOut->Text = "FROM CLIENT: " + ref new Platform::String(wss.str().c_str()); 
    
    					// USE VALUE TO SET A UI ELEMENT
    					Canvas::SetLeft(page->testRectangle, (double)val);
    				});
    				opRead->Start();
    			
    		}
    	});
    	AcceptOperationSocketListener->Start();
    
    

     Anyone have any ideas? Most Socket examples use a blocking call and a while() loop. How do we recursively have the Listener continue to read incoming traffic from the client with the new C++ syntax?
    rk
    Thursday, October 06, 2011 1:37 AM
  • Memeovore,

    Have you had a chance to take a look at the PPL Tasks sample back - Beta version? Here is a link: http://code.msdn.microsoft.com/windowsapps/Windows-8-Asynchronous-08009a0d. There is a utility create_iterative_task in the concurrency::extras namespace (in ppltasks_extra.h) that you may find useful for what you were trying to do last October. Check the ChunkyFileCopySample for how it is used.

    I've attempted to write your sample out using the ppl constructs, but since I'm unable to compile it, I cannot verify that there are no syntax errors.

    MainPage^ page = this; txtOut->Text = "LISTENING FOR CLIENT... "; Windows::Networking::Sockets::StreamSocketListener^ socketListener = ref new StreamSocketListener("192.168.1.76"); socketListener->ServiceName = "8888"; concurrency::extras::create_task(socketListener->AcceptAsync()).then( [page](Windows::Networking::Sockets::StreamSocket^ stream) { page->txtOut->Text += "CLIENT ACCEPTED..."; IInputStream^ inputStream = stream->InputStream; Windows::Storage::Streams::DataReader^ reader = ref new Windows::Storage::Streams::DataReader(inputStream); reader->InputStreamOptions = InputStreamOptions::Partial; concurrency::extras::create_iterative_task([page, reader] { return concurrency::extras::create_task(reader->LoadAsync(4)).then([page, reader](unsigned int val) { if (val > 0)

    { // CONVERT VALUE TO STRING AND DISPLAY IT std::wstringstream wss; wss << val; page->txtOut->Text = "FROM CLIENT: " + ref new Platform::String(wss.str().c_str()); // USE VALUE TO SET A UI ELEMENT Canvas::SetLeft(page->testRectangle, (double)val); }

    // assuming that val is 0 is the terminating condition

    return val == 0; } }); }


    Wednesday, May 09, 2012 9:52 PM
  • I've noticed that ConnectAsync used with a Completed handler does not seem to require an await:

    public async Task TryConnect(Client client, string remoteHostName, string remoteServiceNameOrPort) { StreamSocket socket = new StreamSocket(); HostName hn = new HostName(remoteHostName);//the remote IP address IAsyncAction aa = socket.ConnectAsync(hn, remoteServiceNameOrPort); aa.Completed = new AsyncActionCompletedHandler(

    (IAsyncAction act, AsyncStatus status) => { if(status == AsyncStatus.Completed) { client.status = client.status | Status.Cnctd; } } else if(status == AsyncStatus.Error) { Exception ex = aa.ErrorCode; } else if(status == AsyncStatus.Started) { int x = 1; } else if(status == AsyncStatus.Canceled) { int y = 1; } //await aa; }); }

    and if it is added after the delegate declaration the method will fail with "a delegate was assigned when not allowed" exception message.

    Glenn R.

    Saturday, March 09, 2013 2:11 AM