Pergunta

I have an assignment in which I have to implement a few network protocols. The assignment includes communication over ideal connections (that do not lose or corrupt data) and connections that do corrupt the data. I would like to make this as modular as possible, but I can't figure out how to do it (everything seems so intertwined). Here's a list of things I have to do:

  • Sliding window. This task assumes a perfect connection. However, I would like to abstract away this detail (implement the sliding window code such that handling the quality of the connection is some other module's responsibility).
  • Go-Back-N protocol for an imperfect connection. Here I would like to reuse code from the previous task that involved sliding windows.
  • Selective repeat. This sounds like it should replace the Go-Back-N module, while still working on top of the sliding window module.
  • Error detection. This one looks like it should be independent of whether I use sliding windows, Go-Back-N or selective repeat. Yet, I can't figure out how to separate error checking from message receiving.

Maybe I can implement a layered architecture (inspired by the OSI model), but I'm not sure how to do it. I need a nudge in the right direction.

How should these different modules interact with each other? Such that Go-Back-N or Selective Repeat function independently of whether I want to fill the data link (sliding window) or not, and such that error checking is done on top of all of this, transparently.

Edit: One other difficulty is that some protocols (Go-Back-N, Selective Repeat, Sliding Window) require state particular to that protocol and there's no nice way to implement stateful functions in C.

Foi útil?

Solução

Maybe you could work with chained functions?

Initially, you could have a struct connection with fields like void (*write)(struct connection *con, char *buf, size_t len, void *data);, void *write_data;, int (*get_write_queue_size)(struct connection *con, void *data) and void *get_write_queue_size_data. First, you would fill it with the functions for dealing with an ideal connection.

Then, for adding a sliding window, you would make a struct sliding_window_connection with all the fields from struct connection that you want to intercept. Then, you would move the old functions and data-pointers from the struct connection into the struct sliding_window_connection, replace the functions in the struct connection with the sliding window implementations and replace the data pointers in the struct connection with pointers to the struct sliding_window_connection. The new write could e.g. look somewhat like this:

void sliding_window_connection_write
      (struct connection *con, char *buf, size_t len, void *data) {
  struct sliding_window_connection *swcon = data;
  /* ... do magic for the sliding window ... */
  /* if we want the buffer to be sent now, call the lower layer like this: */
  swcon->write(con, buf, len, swcon->write_data);
}

For stacking go-back-n or selective repeat on top, you would then add the go-back-n or selective repeat functions the same way.

For reading, you would basically do the same – let the data bubble up through the layers and maybe manipulate or interpret it on the way.

To make this work better, you might want to add a function similar to write that can be used by a layer (e.g. go-back-n) to signal a lower layer (e.g. the sliding window) for purposes like "hey, please resend bytes m->n, thanks".

As error detection would have to happen on a higher level than these things, you would have to add it after the other things – the later you add something, the higher its layer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top