I numeri di porta UDP e TCP dovrebbero essere rappresentati come brevi o interi?

2

Attualmente sto progettando un codice di rete, e questo codice si aspetta che il chiamante del codice gli dia una porta e un nome host a cui connettersi.

Dato che sono ancora in fase di sviluppo, posso ancora cambiare molti aspetti del codice e maggiori vantaggi e svantaggi entrano nel codice. Tuttavia, alcuni aspetti del codice mi hanno lasciato ancora a chiedermi quale tipo di numero dovrei passare al codice di creazione del socket sottostante.

Ora devo decidere quale versione dovrei conservare,

Versione 1:

int port = 80;
ServerSocket socket = new ServerSocket(port);

I vantaggi:

  • Quasi tutte le librerie in Java si aspettano numeri interi invece di cortometraggi, incluso InetSocketAddress.

Svantaggi:

  • L'utilizzo di interi anziché di cortocircuiti ha lasciato i suoi bug di sicurezza in passato da sistemi di sicurezza che non eccetto il codice sottostante per saltare i primi 16 bit.

Versione 2:

short port = 80;
ServerSocket socket = new ServerSocket(port);

I vantaggi:

  • Segue la convenzione di sistema sottostante da [C] per usare numeri a 16 bit

Svantaggi:

  • Ci deve essere un motivo per cui java utilizza numeri interi, non è vero?

La mia domanda: dovrei progettare il mio programma in modo che accetti un int o un short

    
posta Ferrybig 23.12.2015 - 11:39
fonte

1 risposta

5

Usa sempre numeri interi, a meno che tu non abbia una buona ragione per fare altrimenti. Qui, in realtà abbiamo una buona ragione: i numeri di porta devono essere compresi nell'intervallo da 0 a 2 16 -1 (vale a dire in un numero a 16 bit senza segno).

Sfortunatamente, il short di Java è un numero firmato a 16 bit, con l'intervallo -2 15 a 2 15 -1. Se utilizzi i corti nella tua API, la porta 65535 dovrebbe essere specificata come -1 . Questo potrebbe essere capito correttamente da una API C che getta il numero su un'interpretazione non firmata, ma all'interno di Java questo porterà a un sacco di dolore non necessario. In particolare, -1 != 65535 , e non puoi facilmente verificare se una determinata porta si trova all'interno di un intervallo di porte.

Se sei preoccupato della correttezza, allora prendi provvedimenti per assicurarti la correttezza. Possiamo modellare un concetto come un "numero di porta valido" come nuovo tipo:

class ValidPortNumber {
  private static final MIN_PORT = 0;
  private static final MAX_PORT = 65535;
  private final int port;
  public ValidPortNumber(int port) {
    if (!(MIN_PORT <= port && port <= MAX_PORT))
      throw ...;
    this.port = port;
  }
  public int get() { return port; }
}

In alternativa, puoi eseguire questa convalida nella tua classe socket.

Perché non possiamo fare affidamento sull'intervallo di valori dei tipi primitivi invece di eseguire la convalida? Quando si mappano concetti (come numeri di porta) a un'implementazione (come i tipi numerici), ci può sempre essere una mancata corrispondenza:

  • alcune istanze del concetto non possono essere mappate all'implementazione, poiché l'implementazione è troppo limitata. Questo succede più o meno se tu avessi scelto short , poiché new ServerSocket(65535) non avrebbe funzionato! Per un'implementazione corretta, è necessario che non esiste alcuna corrispondenza errata.

  • l'implementazione può rappresentare valori che non sono istanze del concetto. Questo succederebbe se usassi int s senza alcuna convalida, poiché new ServerSocket(65536) sarebbe stato accettato. Eliminare questa discrepanza non è strettamente necessario per una corretta implementazione, ma è necessario rilevare l'input falso e rendere l'implementazione resiliente contro i bug di utilizzo.

Quindi ricorda: ogni numero di porta è un numero intero, ma non ogni numero intero è un numero di porta. Pertanto, dovrai scrivere il codice di convalida. Non è possibile utilizzare i cortocircuiti poiché non tutti i numeri di porta sono abbreviati e non tutti i cortometraggi firmati sono un numero di porta.

Esercizi

Le risposte vengono visualizzate al passaggio del mouse sopra la citazione.

  • posso rappresentare il concetto "Indirizzo" come il tipo "String"?

    Yes, every address can be represented as a string. However, I should create a custom type with validation since some strings such as "92hhef92fdff#as" aren't usable addresses.

  • posso rappresentare il concetto "Nome" come il tipo "String"?

    Yes, every name can be written in a Unicode string. Since it is not possible to validate whether a name is “correct”, it is not useful to add a validation type. While some names cannot be expressed in script, this is outside of the scope of any reasonable model of names.

  • posso rappresentare il concetto "Numero telefonico" come il tipo "int"?

    No, for a variety of reasons: leading zeroes might be significant (e.g. for international calls), or because digits might be grouped with spaces, parens, hyphens, … for better readability. Some numbers might use letters as mnemonics for numbers. However, every telephone number can be represented as a sequence of digits (plus perhaps the + and # chars?). We should therefore define a custom type to provide validation and a correct concept of equality, but we could use a string to store the digit sequence and possibly any user-supplied formatting.

risposta data 23.12.2015 - 12:41
fonte

Leggi altre domande sui tag