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?
_answer here_
> Loop Until EOF Character is Received
> - The client continuously reads from the socket using `recv()`, checking if the last byte received is `0x04` (EOF).
> - If the EOF character is detected, the client knows the full response has been received.
> Buffering and Aggregation
> Since `recv()` may return partial data, the client should append data to a buffer until the EOF character is found.
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?
_answer here_
> Use a Terminator Character
> - The protocol can use a special delimiter, such as `\0`(null byte) for commands and `0x04` (EOF) for responses.
> Include Message Length in the Header
> - A fixed-size header can precede each message, specifying the number of bytes in the payload.
> Use a Structured Format (e.g., JSON, XML)
> - While not ideal for simple shell protocols, structured formats like JSON allow parsing with defined message start and end markers.
> Chanllenges:
> - TCP might split a message across multiple `recv()` calls, requiring the client to reconstruct it.
> - TCP might merge multiple commands into one `recv()` call, requiring the client to parse multiple messages properly.
> - If no end delimiter is used, the client may read incomplete commands, leading to unexpected behavior.
3. Describe the general differences between stateful and stateless protocols.
_answer here_
> A stateful protocol maintains session state between client and server across multiple interactions, whereas a stateless protocol treats each request as independent with no retained memory of past interactions.
> Stateful Protocols:
> The server remembers previous interactions. Requires more server-side resources (e.g., memory, session tracking).
> Each request is independent; no session state is stored. Easier to scale since no session tracking is needed.
> Examples:
> - UDP (each packet is independent).
> - HTTP (by default, unless cookies or tokens are used).
> - DNS (each lookup request is processed independently).
4. Our lecture this week stated that UDP is "unreliable". If that is the case, why would we ever use it?
_answer here_
> Although UDP is unreliable, which does not guarantee packet delivery, order, or integrity, it is still useful for applications where speed and low latency are more important than reliability.
> Since there is no connection setup or retransmission, UDP is much faster than TCP, which lower the latency.
> UDP allows sending packets to multiple recipients simultaneously, which is crucial for Streaming video/audio, Online gaming (real-time updates), IoT devices (sensor updates)
> DNS uses UDP because queries are small and fast (retrying is faster than using TCP).
5. What interface/abstraction is provided by the operating system to enable applications to use network communications?
_answer here_
> The operating system provides socket APIs that allow applications to communicate over a network using protocols like TCP and UDP.
> Example:
> Berkeley Sockets API (socket.h)
> Standard API used in C, C++, Python, etc. for network communication.
> Functions:
> socket() → Creates a socket.
> bind() → Binds a socket to an IP/port.
> listen() → Marks a socket for incoming connections.