- Hands-On Network Programming with C# and .NET Core
- Sean Burns
- 983字
- 2021-06-24 16:05:21
Putting it all together
Now, we've seen how the OSI model organizes the responsibilities of transmitting data. Hopefully, by this point, it should be clear how each layer in the stack is intended to provide a reliable abstraction for the layer above it. However, the process of communicating with a remote host, in its entirety, may still seem a bit vague. So, let's consider a concrete example and address each of the concepts that we talked about as they arise through the process of data transmission.
First, let's assume that an entity on layer 5 of our host (the session layer) wants to establish a session with an entity on Layer 5 in a remote host. I haven't said so explicitly until now, but we can always assume that an entity on a given layer on one host only ever communicates directly with a corresponding entity on the same layer in the remote host. So, for our example, an entity in layer 5 will communicate with a remote entity that also resides in layer 5.
Communicating with remote entities will always happen through a protocol. Given this, the first responsibility of any entity seeking to communicate with a remote host is to wrap the transmitted data in the headers and footers appropriate for that protocol. For our entity in the session layer, let's assume they are hoping to establish a session using the Session Control Protocol (SCP). This means that our local entity will produce the data necessary to establish a session, then wrap that data in SCP headers and footers, creating a well-formed PDU (hopefully, this makes it clear why the name describes this package). This ensures that the recipient host will be able to unwrap the data based on the information stored in the headers and footers of our PDU.
Since entities that reside on any layer above the physical layer cannot communicate directly with one another, we have to pass our PDU down the stack. In our example, we can reliably pass the PDU down to Layer 4 by taking advantage of its service definition and trusting that the logical operations exposed through that definition are accurately implemented by all of the responsible entities below Layer 5. So, we don't need to know how Layer 4 implements transport mechanisms. Instead, we simply ask it to use the appropriate transport mechanism for this particular instance and trust that it will do so appropriately.
This pattern of trusting that lower layers in the stack will correctly implement the operations being requested by higher layers in the stack continues all the way through to Layer 1. Over the course of this process, each layer in the stack will wrap the PDU in its own headers and footers. These standardized chunks of data give each intermediary layer on the receiving host enough information to know to pass the PDU up its own stack. By continuously wrapping the data in well-formed, well-understood chunks of binary data, each layer on the remote host can trust that the inner segment of data that is passed up the stack is exactly what should move up.
This process of wrapping the PDU in deeper and deeper layers of metadata continues down the stack until we reach Layer 1. Layer 1 holds the physical connection from our host to the remote host. Once we've reached this level, we can step across the expanse of the network and start looking at how our PDU moves back up the network stack until it reaches our target entity on Layer 5. Entities on each layer of the remote host will diligently remove and read the headers and footers applied by the corresponding layer of the originating host. The information in those wrappers will indicate that the PDU is destined for a layer above the current layer, and so entities will simply strip their headers and bubble the rest of the data up the network stack.
Once the data has reached layer 5 on the remote host, an entity on that layer will read the headers and footers of the PDU that were applied on Layer 5 of the originating host. This metadata will indicate that layer 5 is, in fact, the target layer for this particular PDU. The metadata will also indicate what protocol should be used to parse the data passed to the remote host. Using this information, the recipient host will have enough data to properly read the data in the PDU, and construct its own response PDU.
Once that response is received by the originating host, a session will be established, and be open for use by any entities above the session layer in the originating or remote host. This whole process is captured in the following diagram of the full life cycle of data transmission through the OSI stack:
With this diagram in mind, is easy to see how the standardization provided by the OSI model makes it easier for engineers to program software for networks. The clean separation of concerns and the explicit pattern for passing data through the stack allows for well-formed contracts, against which all interested parties can design and develop. Engineers programming entities on the application layer can ignore the details of transporting data. They simply pass down a well-formed PDU through the stack.
Hopefully, this description clarifies how entities on specific layers expose their abstractions through a service definition, and how entities operating on the same layer of the network stack on different hosts reliably communicate through protocols. With this perspective in mind, let's take a closer look at the layers of this stack that we'll be programming for most frequently, as well as looking at some of the classes that C# provides to represent the entities of these layers.