Skip to content

Commit

Permalink
Refreshes Retype-generated documentation.
Browse files Browse the repository at this point in the history
Process triggered by cwoodruff.
  • Loading branch information
Retype GitHub Action committed Apr 11, 2024
1 parent 8b20af2 commit 8662589
Show file tree
Hide file tree
Showing 33 changed files with 178 additions and 151 deletions.
8 changes: 4 additions & 4 deletions 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-root" content="/book-network-programming-csharp">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109411615">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109924794">

<!-- See retype.com -->
<meta name="generator" content="Retype 3.5.0">
Expand All @@ -32,11 +32,11 @@
<script data-cfasync="false">(function () { var el = document.documentElement, m = localStorage.getItem("doc_theme"), wm = window.matchMedia; if (m === "dark" || (!m && wm && wm("(prefers-color-scheme: dark)").matches)) { el.classList.add("dark") } else { el.classList.remove("dark") } })();</script>

<link href="/book-network-programming-csharp/images/favicon.png" rel="icon">
<link href="/book-network-programming-csharp/resources/css/retype.css?v=3.5.0.766109411615" rel="stylesheet">
<link href="/book-network-programming-csharp/resources/css/retype.css?v=3.5.0.766109924794" rel="stylesheet">

<script data-cfasync="false" src="/book-network-programming-csharp/resources/js/config.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="/book-network-programming-csharp/resources/js/config.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="/book-network-programming-csharp/resources/js/retype.js?v=3.5.0" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="/book-network-programming-csharp/resources/js/lunr.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="/book-network-programming-csharp/resources/js/lunr.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
</head>
<body>
<div id="docs-app" class="relative text-base antialiased text-gray-700 bg-white font-body dark:bg-dark-850 dark:text-dark-300">
Expand Down
8 changes: 4 additions & 4 deletions acknowledgments/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-root" content="/book-network-programming-csharp">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109411615">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109924794">

<!-- See retype.com -->
<meta name="generator" content="Retype 3.5.0">
Expand Down Expand Up @@ -35,11 +35,11 @@
<script data-cfasync="false">(function () { var el = document.documentElement, m = localStorage.getItem("doc_theme"), wm = window.matchMedia; if (m === "dark" || (!m && wm && wm("(prefers-color-scheme: dark)").matches)) { el.classList.add("dark") } else { el.classList.remove("dark") } })();</script>

<link href="../images/favicon.png" rel="icon">
<link href="../resources/css/retype.css?v=3.5.0.766109411615" rel="stylesheet">
<link href="../resources/css/retype.css?v=3.5.0.766109924794" rel="stylesheet">

<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/retype.js?v=3.5.0" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
</head>
<body>
<div id="docs-app" class="relative text-base antialiased text-gray-700 bg-white font-body dark:bg-dark-850 dark:text-dark-300">
Expand Down
8 changes: 4 additions & 4 deletions authorbio/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-root" content="/book-network-programming-csharp">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109411615">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109924794">

<!-- See retype.com -->
<meta name="generator" content="Retype 3.5.0">
Expand Down Expand Up @@ -35,11 +35,11 @@
<script data-cfasync="false">(function () { var el = document.documentElement, m = localStorage.getItem("doc_theme"), wm = window.matchMedia; if (m === "dark" || (!m && wm && wm("(prefers-color-scheme: dark)").matches)) { el.classList.add("dark") } else { el.classList.remove("dark") } })();</script>

<link href="../images/favicon.png" rel="icon">
<link href="../resources/css/retype.css?v=3.5.0.766109411615" rel="stylesheet">
<link href="../resources/css/retype.css?v=3.5.0.766109924794" rel="stylesheet">

<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/retype.js?v=3.5.0" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
</head>
<body>
<div id="docs-app" class="relative text-base antialiased text-gray-700 bg-white font-body dark:bg-dark-850 dark:text-dark-300">
Expand Down
8 changes: 4 additions & 4 deletions chapter01/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-root" content="/book-network-programming-csharp">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109411615">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109924794">

<!-- See retype.com -->
<meta name="generator" content="Retype 3.5.0">
Expand Down Expand Up @@ -37,11 +37,11 @@
<script data-cfasync="false">(function () { var el = document.documentElement, m = localStorage.getItem("doc_theme"), wm = window.matchMedia; if (m === "dark" || (!m && wm && wm("(prefers-color-scheme: dark)").matches)) { el.classList.add("dark") } else { el.classList.remove("dark") } })();</script>

<link href="../images/favicon.png" rel="icon">
<link href="../resources/css/retype.css?v=3.5.0.766109411615" rel="stylesheet">
<link href="../resources/css/retype.css?v=3.5.0.766109924794" rel="stylesheet">

<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/retype.js?v=3.5.0" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
</head>
<body>
<div id="docs-app" class="relative text-base antialiased text-gray-700 bg-white font-body dark:bg-dark-850 dark:text-dark-300">
Expand Down
8 changes: 4 additions & 4 deletions chapter02/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-root" content="/book-network-programming-csharp">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109411615">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109924794">

<!-- See retype.com -->
<meta name="generator" content="Retype 3.5.0">
Expand Down Expand Up @@ -37,11 +37,11 @@
<script data-cfasync="false">(function () { var el = document.documentElement, m = localStorage.getItem("doc_theme"), wm = window.matchMedia; if (m === "dark" || (!m && wm && wm("(prefers-color-scheme: dark)").matches)) { el.classList.add("dark") } else { el.classList.remove("dark") } })();</script>

<link href="../images/favicon.png" rel="icon">
<link href="../resources/css/retype.css?v=3.5.0.766109411615" rel="stylesheet">
<link href="../resources/css/retype.css?v=3.5.0.766109924794" rel="stylesheet">

<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/retype.js?v=3.5.0" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
</head>
<body>
<div id="docs-app" class="relative text-base antialiased text-gray-700 bg-white font-body dark:bg-dark-850 dark:text-dark-300">
Expand Down
91 changes: 59 additions & 32 deletions chapter03/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="turbo-root" content="/book-network-programming-csharp">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109411615">
<meta name="turbo-cache-control" content="no-cache" data-turbo-track="reload" data-track-token="3.5.0.766109924794">

<!-- See retype.com -->
<meta name="generator" content="Retype 3.5.0">
Expand Down Expand Up @@ -35,12 +35,12 @@
<script data-cfasync="false">(function () { var el = document.documentElement, m = localStorage.getItem("doc_theme"), wm = window.matchMedia; if (m === "dark" || (!m && wm && wm("(prefers-color-scheme: dark)").matches)) { el.classList.add("dark") } else { el.classList.remove("dark") } })();</script>

<link href="../images/favicon.png" rel="icon">
<link href="../resources/css/retype.css?v=3.5.0.766109411615" rel="stylesheet">
<link href="../resources/css/retype.css?v=3.5.0.766109924794" rel="stylesheet">

<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/config.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script data-cfasync="false" src="../resources/js/retype.js?v=3.5.0" data-turbo-eval="false" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109411615" data-turbo-eval="false" defer></script>
<script id="prism-js" data-cfasync="false" src="../resources/js/prism.js?v=3.5.0.766109411615" defer></script>
<script id="lunr-js" data-cfasync="false" src="../resources/js/lunr.js?v=3.5.0.766109924794" data-turbo-eval="false" defer></script>
<script id="prism-js" data-cfasync="false" src="../resources/js/prism.js?v=3.5.0.766109924794" defer></script>
</head>
<body>
<div id="docs-app" class="relative text-base antialiased text-gray-700 bg-white font-body dark:bg-dark-850 dark:text-dark-300">
Expand Down Expand Up @@ -936,40 +936,67 @@ <h3>
<span>Handling data of unknown length</span>
</h3>
</doc-anchor-target>
<p>When the client isn&#x27;t aware of the size of the incoming data, a loop can be employed to keep receiving data until the server finishes sending. Here&#x27;s an approach to handle such scenarios:</p>
<p>Handling UTF-8 decoding from a potentially incomplete buffer, especially when dealing with length-prefixed data, involves careful planning around the data you read and ensuring that multi-byte characters are not split across read operations. Here&#x27;s a strategy that addresses both concerns and also explores data deserialization:</p>
<p><strong>Decoding UTF-8 with Potentially Incomplete Buffers</strong></p>
<p>Since multi-byte UTF-8 sequences can be split across buffer boundaries, you need a way to store incomplete sequences and attempt decoding once more data is available. This requires maintaining a state between reads, which can be achieved using the System.Text.Decoder class, as mentioned earlier. It&#x27;s crucial to handle the edge case where the buffer ends in the middle of a multi-byte character.</p>
<p><strong>Handling Length-Prefixed Data</strong></p>
<p>When dealing with length-prefixed messages, the length header must be read completely to know how many bytes need to be read for the complete message. This often means reading from the stream in a loop until all parts of the length prefix have been received. Once you have the length, you continue reading until you&#x27;ve received the entire message as indicated by the length prefix. This might mean accumulating data across multiple reads.</p>
<div class="codeblock-wrapper"><doc-codeblock>
<pre class="language-csharp"><code v-pre class="language-csharp">byte[] buffer = new byte[1024];
int totalBytesReceived = 0;
StringBuilder messageBuilder = new StringBuilder();

while (true)
<pre class="language-csharp"><code v-pre class="language-csharp">public class LengthPrefixedMessageReader
{
int bytesReceived = clientSocket.Receive(buffer);
private readonly Stream _stream;
private readonly Decoder _utf8Decoder;

if (bytesReceived == 0) break; // Server closed the connection

totalBytesReceived += bytesReceived;
public LengthPrefixedMessageReader(Stream stream)
{
_stream = stream;
_utf8Decoder = Encoding.UTF8.GetDecoder();
}

messageBuilder.Append(Encoding.UTF8.GetString(buffer, 0, bytesReceived));
}
public async Task&lt;string&gt; ReadMessageAsync()
{
// Assume the length prefix is always 4 bytes (int32)
byte[] lengthPrefix = new byte[4];
int bytesRead = await ReadExactAsync(_stream, lengthPrefix, 0, lengthPrefix.Length);
if (bytesRead &lt; lengthPrefix.Length) throw new Exception(&quot;Failed to read the length prefix.&quot;);

int messageLength = BitConverter.ToInt32(lengthPrefix, 0);
byte[] messageBytes = new byte[messageLength];
bytesRead = await ReadExactAsync(_stream, messageBytes, 0, messageLength);
if (bytesRead &lt; messageLength) throw new Exception(&quot;Failed to read the complete message.&quot;);

// Decode potentially incomplete UTF-8 bytes
char[] chars = new char[_utf8Decoder.GetCharCount(messageBytes, 0, bytesRead)];
int charCount = _utf8Decoder.GetChars(messageBytes, 0, bytesRead, chars, 0);
return new string(chars, 0, charCount);
}

string fullMessage = messageBuilder.ToString();</code></pre>
</doc-codeblock></div>
<p>Having explored the intricacies of client-side socket programming, we are now well-versed in initiating connections, sending requests, and handling responses. This understanding is crucial as we transition to server-side socket programming, where we will shift our focus from initiating to accepting connections, managing multiple clients, and maintaining robust communication channels. The server side completes the communication loop, empowering us to architect full-fledged network applications with C#. Ensuring complete data reception</p>
<p>The following are some best practices to ensure data is fully received:</p>
<p><strong>Delimiters or Length Prefixes</strong>: One common approach is for the server to send a specific delimiter indicating the end of a message or prefix the message with its length. This helps the client understand when it has received the complete data.</p>
<p><strong>Error Handling</strong>: Network operations can be unpredictable. As with sending data, wrapping the Receive method in a try-catch block is crucial to handle potential issues:</p>
<div class="codeblock-wrapper"><doc-codeblock>
<pre class="language-csharp"><code v-pre class="language-csharp">try
{
clientSocket.Receive(buffer);
}
catch (SocketException e)
{
Console.WriteLine($&quot;An error occurred while receiving data: {e.Message}&quot;);
private async Task&lt;int&gt; ReadExactAsync(Stream stream, byte[] buffer, int offset, int count)
{
int totalBytesRead = 0;
while (totalBytesRead &lt; count)
{
int bytesRead = await stream.ReadAsync(buffer, offset + totalBytesRead, count - totalBytesRead);
if (bytesRead == 0)
{
// End of stream
break;
}
totalBytesRead += bytesRead;
}
return totalBytesRead;
}
}</code></pre>
</doc-codeblock></div>
<p><strong>Data Deserialization</strong>: If the server is sending complex data structures, the client may need to deserialize the received byte array back into the original object or structure.</p>
<p>In this implementation, we have examples of the following:</p>
<ul>
<li><strong>Length Prefix Handling</strong>: The message length is prefixed as a 4-byte integer. It&#x27;s read entirely before attempting to read the message itself.</li>
<li><strong>Message Reading</strong>: The message is read entirely based on the length prefix. This step ensures that you&#x27;re working with complete data, even if multiple reads are necessary to get all the bytes.</li>
<li><strong>UTF-8 Decoding</strong>: The Decoder instance is used to handle UTF-8 decoding. While this example assumes that the entire message is received before decoding, the Decoder&#x27;s stateful nature allows it to handle partial sequences across calls if you decode as you read instead.</li>
</ul>
<p>This strategy effectively addresses the challenges of reading length-prefixed data and decoding UTF-8 from streams, especially in scenarios where data boundaries do not align with message or character boundaries.</p>
<p><strong>Data Deserialization</strong></p>
<p>If the server is sending complex data structures, the client may need to deserialize the received byte array back into the original object or structure.</p>
<div class="codeblock-wrapper"><doc-codeblock>
<pre class="language-csharp"><code v-pre class="language-csharp">using System;
using System.Net;
Expand Down
Loading

0 comments on commit 8662589

Please sign in to comment.