1. How does the remote client determine when a command's output is fully received from the server, and what techniques can be used to handle partial reads or ensure complete message transmission?
The server appends a specified end-of-stream marker (in our example, the ASCII 0x04, defined as RDSH_EOF_CHAR) to the whole output of a command, which the remote client depends on. Until it finds this marker, which signifies that the full message has been received, the client keeps calling recv() to read from the socket. The client loops, gathering information into a buffer until the EOF marker is located, in order to accommodate incomplete readings (since TCP may divide messages arbitrarily). Additional strategies include prefixing the length of each message so that the recipient is aware of the precise number of bytes to anticipate. Without these safeguards, the client might unintentionally combine portions of consecutive messages or handle incomplete data.
2. This week's lecture on TCP explains that it is a reliable stream protocol rather than a message-oriented one. Since TCP does not preserve message boundaries, how should a networked shell protocol define and detect the beginning and end of a command sent over a TCP connection? What challenges arise if this is not handled correctly?
Message boundaries should be clearly defined by a networked shell protocol. This is often done by prefixing messages with a fixed-size length field or by adding a unique delimiter (for example, a null byte for incoming commands and an EOF character like RDSH_EOF_CHAR for outgoing answers). Even though TCP delivers a continuous stream of bytes, this allows the recipient to know precisely when one command stops and the next one begins. Multiple messages may merge together, incomplete messages may be mistakenly perceived as full, and the protocol state may go out of sync if message boundaries are not appropriately identified and established. Incorrect command execution or even a total breakdown in communication may result from this.
3. Describe the general differences between stateful and stateless protocols.
Between requests, stateful protocols save session state; the server "remembers" past exchanges with a client, and these stored states affect how subsequent requests are handled. Protocols with permanent connections and session cookies, such as FTP or HTTP, are examples. Stateless protocols, on the other hand, do not keep track of previous exchanges; instead, every request is unique and needs to provide all relevant data for processing. HTTP/1.0 is a popular example, in which each request is self-contained. In contrast to stateless protocols, which are more straightforward and scalable but may need more client effort to handle context, stateful protocols can provide deeper interactions at the expense of increased resource consumption and complexity.
4. Our lecture this week stated that UDP is "unreliable". If that is the case, why would we ever use it?
UDP has less overhead and delay than TCP, despite the fact that it is "unreliable" since it cannot ensure delivery, order, or error recovery. For real-time applications (like VoIP, online gaming, or streaming video) where speed is more important than flawless dependability, or for applications that use their own error-checking and correction, UDP is therefore excellent. Additionally, UDP works well for multicasting, or sending data to several recipients at once.
5. What interface/abstraction is provided by the operating system to enable applications to use network communications?
Network communication details are abstracted into a collection of system calls (socket(), bind(), listen(), accept(), connect(), transmit(), and recv()) by the operating system's sockets API. While concealing the intricate details of network hardware and protocol processing, sockets enable programs to connect and exchange data across networks using a variety of protocols (such as TCP and UDP).