Streamsocket example c# metro

3 minute read

Peter Daukintis

This is a very basic example of socket communication in a c# metro-style application using StreamSocket and StreamSocketListener. It mirrors the Simple StreamSocket example in msdn here http://code.msdn.microsoft.com/windowsapps/StreamSocket-Sample-8c573931 which is coded in c++ and javascript but no c#. I decided to roughly convert it as a learning exercise – please note I haven’t tested the code in that many scenarios and haven’t handled failure cases and errors much.

A socket provides send and receive over TCP and a StreamSocketListener will listen for incoming TCP connections.

The sample will act as a server or client depending on which buttons you press, i.e. press listen to be a server and connect to be a client. Also, you can set the same program as client and server ad have it communicate with itself.

To start the listener wire up a connection received event handler and bind the service name…

<div style="margin:0;display:inline;float:none;padding:0;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:89d531e7-e509-4ddf-9ff6-b302a25f71b6" class="wlWriterEditableSmartContent"> <div style="border:#000080 1px solid;color:#000;font-family:'Courier New', Courier, Monospace;font-size:10pt;"> <div style="background-color:#000000;overflow:auto;padding:2px 5px;"><span style="background:#1e1e1e;color:#c8c8c8;">_listener</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">ConnectionReceived </span><span style="background:#1e1e1e;color:#9b9b9b;">+=</span><span style="background:#1e1e1e;color:#c8c8c8;"> listenerConnectionReceived;</span><br> <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">await</span><span style="background:#1e1e1e;color:#c8c8c8;"> _listener</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">BindServiceNameAsync(</span><span style="background:#1e1e1e;color:#d69d85;">&quot;3011&quot;</span><span style="background:#1e1e1e;color:#c8c8c8;">);</span></div> </div> </div>    <p>The event handler stores the incoming socket in a list (so it can use it to reply), and waits for incoming data from it. The ‘waiting for incoming data’ bit looks like this…</p>  <div style="margin:0;display:inline;float:none;padding:0;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:081a12f3-a67f-41bd-bd22-e9841702efdd" class="wlWriterEditableSmartContent"> <div style="border:#000080 1px solid;color:#000;font-family:'Courier New', Courier, Monospace;font-size:10pt;"> <div style="background-color:#000000;overflow:auto;padding:2px 5px;"><span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">async</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">private</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">void</span><span style="background:#1e1e1e;color:#c8c8c8;"> WaitForData(</span><span style="background:#1e1e1e;color:#4ec9b0;">StreamSocket</span><span style="background:#1e1e1e;color:#c8c8c8;"> socket)</span><br> <span style="background:#1e1e1e;color:#c8c8c8;">{</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">var</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">new</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#4ec9b0;">DataReader</span><span style="background:#1e1e1e;color:#c8c8c8;">(socket</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">InputStream);</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#608b4e;">//dr.InputStreamOptions = InputStreamOptions.Partial;</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">var</span><span style="background:#1e1e1e;color:#c8c8c8;"> stringHeader </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">await</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">LoadAsync(</span><span style="background:#1e1e1e;color:#b5cea8;">4</span><span style="background:#1e1e1e;color:#c8c8c8;">);</span><br> <br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">if</span><span style="background:#1e1e1e;color:#c8c8c8;"> (stringHeader </span><span style="background:#1e1e1e;color:#9b9b9b;">==</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#b5cea8;">0</span><span style="background:#1e1e1e;color:#c8c8c8;">)</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;">{</span><br>         <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#608b4e;">// disconnected</span><br>         <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">return</span><span style="background:#1e1e1e;color:#c8c8c8;">;</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;">}</span><br> <br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">int</span><span style="background:#1e1e1e;color:#c8c8c8;"> strLength </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">ReadInt32();</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">uint</span><span style="background:#1e1e1e;color:#c8c8c8;"> numStrBytes </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">await</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">LoadAsync((</span><span style="background:#1e1e1e;color:#569cd6;">uint</span><span style="background:#1e1e1e;color:#c8c8c8;">)strLength);</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">string</span><span style="background:#1e1e1e;color:#c8c8c8;"> msg </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">ReadString(numStrBytes);</span><br>     <span style="background:#1e1e1e;color:#c8c8c8;">WaitForData(socket);</span><br> <span style="background:#1e1e1e;color:#c8c8c8;">}</span></div> </div> </div>  <p>It uses a DataReader to read from the incoming socket and then calls itself to wait for subsequent incoming message data.</p>  <p>Note that the samples use a protocol which sends the length (number of bytes) of the message first followed by the message data itself. If you want to use a different strategy, for example characters to delimit the start and end of a message then the code will change a little bit. The difference being that you won’t always know how much data to read. You can modify the code like this to accommodate this:</p>  <div style="margin:0;display:inline;float:none;padding:0;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9d320c57-51dd-4510-a7af-299a1902fef6" class="wlWriterEditableSmartContent"> <div style="border:#000080 1px solid;color:#000;font-family:'Courier New', Courier, Monospace;font-size:10pt;"> <div style="background-color:#000000;overflow:auto;padding:2px 5px;"><span style="background:#1e1e1e;color:#569cd6;">async</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">private</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">void</span><span style="background:#1e1e1e;color:#c8c8c8;"> WaitForData(</span><span style="background:#1e1e1e;color:#4ec9b0;">StreamSocket</span><span style="background:#1e1e1e;color:#c8c8c8;"> socket)</span><br>         <span style="background:#1e1e1e;color:#c8c8c8;">{</span><br>             <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">var</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">new</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#4ec9b0;">DataReader</span><span style="background:#1e1e1e;color:#c8c8c8;">(socket</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">InputStream);</span><br>             <span style="background:#1e1e1e;color:#c8c8c8;">dr</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">InputStreamOptions </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#b8d7a3;">InputStreamOptions</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">Partial;</span><br>             <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#569cd6;">var</span><span style="background:#1e1e1e;color:#c8c8c8;"> stringHeader </span><span style="background:#1e1e1e;color:#9b9b9b;">=</span><span style="background:#1e1e1e;color:#c8c8c8;"> </span><span style="background:#1e1e1e;color:#569cd6;">await</span><span style="background:#1e1e1e;color:#c8c8c8;"> dr</span><span style="background:#1e1e1e;color:#9b9b9b;">.</span><span style="background:#1e1e1e;color:#c8c8c8;">LoadAsync(</span><span style="background:#1e1e1e;color:#b5cea8;">512</span><span style="background:#1e1e1e;color:#c8c8c8;">);</span><br> <br>             <span style="background:#1e1e1e;color:#c8c8c8;"></span><span style="background:#1e1e1e;color:#608b4e;">// change the rest acccordingly....</span></div> </div> </div>  <p>Note that setting the InputStreamOptions to Partial will allow you to specify a larger buffer but also the async load operation will complete when a smaller sized buffer comes in. This enables you to read the data coming in and respond to it accordingly.</p>  <p>The pictures show a session between a socket server running on a build slate and a win8 vm both on my local network..</p>  <p><a href="/assets/images/2012/04/socketexampleservertablet.jpg"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="socketexampleservertablet" border="0" alt="socketexampleservertablet" src="/assets/images/2012/04/socketexampleservertablet_thumb.jpg" width="645" height="512" /></a></p>  <p><a href="/assets/images/2012/04/socketexampleclientvm.jpg"><img style="background-image:none;padding-left:0;padding-right:0;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0;border-width:0;" title="socketexampleclientvm" border="0" alt="socketexampleclientvm" src="/assets/images/2012/04/socketexampleclientvm_thumb.jpg" width="645" height="504" /></a></p>  <p>The project can be downloaded from here.</p>  <p><a title="https://skydrive.live.com/redir.aspx?cid=4f1b7368284539e5&amp;resid=4F1B7368284539E5!445&amp;parid=4F1B7368284539E5!123" href="https://skydrive.live.com/redir.aspx?cid=4f1b7368284539e5&amp;resid=4F1B7368284539E5!445&amp;parid=4F1B7368284539E5!123">https://skydrive.live.com/redir.aspx?cid=4f1b7368284539e5&amp;resid=4F1B7368284539E5!445&amp;parid=4F1B7368284539E5!123</a></p>  <p>UPDATE: This project has been updated for the Release Preview</p>  <p><a title="http://sdrv.ms/Nema94" href="http://sdrv.ms/Nema94">http://sdrv.ms/Nema94</a></p>

Comments