From 56927aba1f982ad7bfcbd5d331b0f73f71d355d3 Mon Sep 17 00:00:00 2001 From: cozis Date: Thu, 29 Jun 2023 19:38:44 +0200 Subject: [PATCH] clean up of files and fixed docs --- .gitignore | 2 + xjson.c => 3p/xjson.c | 0 xjson.h => 3p/xjson.h | 0 README.md | 2 +- example/example.json | 5 + example/example.tt | 18 + makefile | 4 +- page.html | 13 - page2.html | 19 - params.json | 12 - cli.c => src/cli.c | 73 +- tinytemplate.c => src/tinytemplate.c | 103 ++- tinytemplate.h => src/tinytemplate.h | 2 +- test.html | 1236 -------------------------- tt | Bin 105296 -> 0 bytes tt.exe | Bin 160242 -> 162873 bytes 16 files changed, 161 insertions(+), 1328 deletions(-) create mode 100644 .gitignore rename xjson.c => 3p/xjson.c (100%) rename xjson.h => 3p/xjson.h (100%) create mode 100644 example/example.json create mode 100644 example/example.tt delete mode 100644 page.html delete mode 100644 page2.html delete mode 100644 params.json rename cli.c => src/cli.c (78%) rename tinytemplate.c => src/tinytemplate.c (94%) rename tinytemplate.h => src/tinytemplate.h (97%) delete mode 100644 test.html delete mode 100644 tt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2fb5b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +tt +tt.exe \ No newline at end of file diff --git a/xjson.c b/3p/xjson.c similarity index 100% rename from xjson.c rename to 3p/xjson.c diff --git a/xjson.h b/3p/xjson.h similarity index 100% rename from xjson.h rename to 3p/xjson.h diff --git a/README.md b/README.md index b067f39..a490cb4 100644 --- a/README.md +++ b/README.md @@ -50,4 +50,4 @@ cat page.tt | ./tt params.json > page.html ``` ## Internals -TinyTemplate works by compiling a template string into a bytecode program, and then evaluating the program to generate the output. \ No newline at end of file +TinyTemplate works by compiling a template string into a bytecode program, and then evaluating the program to generate the output. (TODO) \ No newline at end of file diff --git a/example/example.json b/example/example.json new file mode 100644 index 0000000..8ff9bfa --- /dev/null +++ b/example/example.json @@ -0,0 +1,5 @@ +{ + "name": "Francesco", + "fruits": ["Orange", "Peach", "Mango"], + "chocolate": false +} \ No newline at end of file diff --git a/example/example.tt b/example/example.tt new file mode 100644 index 0000000..180ec87 --- /dev/null +++ b/example/example.tt @@ -0,0 +1,18 @@ + + + TinyTemplate example + + + Hello, my name is {{name}} and my favourite fruits are: + + {% if chocolate %} + but I also like chocolate! + {% else %} + and I do NOT like chocolate! + {% end %} + + \ No newline at end of file diff --git a/makefile b/makefile index 0ad2b06..ff4c9dc 100644 --- a/makefile +++ b/makefile @@ -1,8 +1,8 @@ all: tt -tt: cli.c tinytemplate.c xjson.c - gcc $^ -o $@ -Wall -Wextra -g +tt: src/cli.c src/tinytemplate.c 3p/xjson.c + gcc $^ -o $@ -Wall -Wextra -g -I3p clean: rm tt tt.exe diff --git a/page.html b/page.html deleted file mode 100644 index dde8008..0000000 --- a/page.html +++ /dev/null @@ -1,13 +0,0 @@ - - - {{username}}s blog! - - -

Hei, welcome to my blog! I'm {{name}} {{surname}} and I'm {{age}} years old!

- - - \ No newline at end of file diff --git a/page2.html b/page2.html deleted file mode 100644 index 741126a..0000000 --- a/page2.html +++ /dev/null @@ -1,19 +0,0 @@ - - - coziss blog! - - -

Hei, welcome to my blog! I'm Francesco Cozzuto and I'm 24 years old!

- - - \ No newline at end of file diff --git a/params.json b/params.json deleted file mode 100644 index 6be63fd..0000000 --- a/params.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "username": "cozis", - "name": "Francesco", - "surname": "Cozzuto", - "age": 24, - "posts": [ - {"title": "Scriviamo un server TCP", "date": "10/9/2023"}, - {"title": "Gli assert", "date": "4/5/2022"}, - {"title": "Big e little endian: Ordinamento dei byte", "date": "14/5/2022"}, - {"title": "Complessità computazionale", "date": "???"} - ] -} diff --git a/cli.c b/src/cli.c similarity index 78% rename from cli.c rename to src/cli.c index 589e5f0..0b2a9ce 100644 --- a/cli.c +++ b/src/cli.c @@ -6,28 +6,30 @@ #include "tinytemplate.h" typedef struct wrap_t wrap_t; +typedef struct eval_context_t eval_context_t; + struct wrap_t { eval_context_t *context; union { xj_value *value; - wrap_t *next; + wrap_t *next; }; }; -typedef struct { +struct eval_context_t { FILE *stream; - xj_value *params; - wrap_t *free; - wrap_t pool[TINYTEMPLATE_MAX_ITER_DEPTH]; -} eval_context_t; + wrap_t params; + wrap_t *free; + wrap_t pool[TINYTEMPLATE_MAX_ITER_DEPTH]; +}; static bool query_json_array(void *data, tinytemplate_type_t *type, tinytemplate_value_t *value); static bool query_json_object(void *data, const char *key, size_t len, - tinytemplate_type_t *type, - tinytemplate_value_t *value); + tinytemplate_type_t *type, + tinytemplate_value_t *value); static void convert_json_object(eval_context_t *context, xj_value *child, @@ -58,13 +60,14 @@ static void convert_json_object(eval_context_t *context, case XJ_ARRAY: { - iter_t *iter = context->free; + wrap_t *wrap = context->free; *type = TINYTEMPLATE_TYPE_ARRAY; - value->as_array.data = iter; - value->as_array.next = query_json_array; - if (iter) { - context->free = iter->next; - iter->curs = child->as_array; + value->as_array.data = wrap; + value->as_array.next = query_json_array; + if (wrap) { + context->free = wrap->next; + wrap->value = child->as_array; + wrap->context = context; } break; } @@ -87,14 +90,12 @@ static bool query_json_array(void *data, tinytemplate_type_t *type, tinytemplate_value_t *value) { - iter_t *iter = data; - - if (iter->curs) { - iter->curs = iter->curs->next; - if (iter->curs) { - convert_json_object(iter->curs, type, value); - return true; - } + wrap_t *wrap = data; + + if (wrap->value) { + convert_json_object(wrap->context, wrap->value, type, value); + wrap->value = wrap->value->next; + return true; } return false; } @@ -103,10 +104,11 @@ static bool query_json_object(void *data, const char *key, size_t len, tinytemplate_type_t *type, tinytemplate_value_t *value) { - xj_value *json_value = data; - assert(json_value->type == XJ_OBJECT); + wrap_t *wrap = data; + + assert(wrap->value->type == XJ_OBJECT); - xj_value *child = json_value->as_object; + xj_value *child = wrap->value->as_object; while (child) { size_t keylen = strlen(child->key); if (keylen == len && !strncmp(key, child->key, len)) @@ -116,12 +118,16 @@ static bool query_json_object(void *data, const char *key, size_t len, if (!child) return false; - convert_json_object(child, type, value); + convert_json_object(wrap->context, child, type, value); return true; } -static void callback(void *userp, const char *str, size_t len) +static void callback(void *userp, const char *lbl, size_t lbllen, + const char *str, size_t len) { + (void) lbl; + (void) lbllen; + eval_context_t *context = userp; fwrite(str, 1, len, context->stream); } @@ -131,8 +137,8 @@ static bool query_root_json_object(void *data, const char *key, size_t len, tinytemplate_value_t *value) { eval_context_t *context = data; - if (context->params) - return query_json_object(context->params, key, len, type, value); + if (context->params.value) + return query_json_object(&context->params, key, len, type, value); else return false; } @@ -140,9 +146,10 @@ static bool query_root_json_object(void *data, const char *key, size_t len, static void init_context(eval_context_t *context, FILE *stream, xj_value *root) { - context->stream=stdout; - context->params=root; - context->free = context->pool; + context->stream = stream; + context->params.context = context; + context->params.value = root; + context->free = context->pool; for (int i = 0; i < TINYTEMPLATE_MAX_ITER_DEPTH-1; i++) context->pool[i].next = &context->pool[i+1]; @@ -217,7 +224,7 @@ int main(int argc, char **argv) } while (status == TINYTEMPLATE_STATUS_EMEMORY); eval_context_t context; - init_context(&context); + init_context(&context, stdout, root); if (tinytemplate_eval(buffer, program, &context, query_root_json_object, callback, message, sizeof(message)) != TINYTEMPLATE_STATUS_DONE) { fprintf(stderr, "Failed to evaluate template (%s)\n", message); diff --git a/tinytemplate.c b/src/tinytemplate.c similarity index 94% rename from tinytemplate.c rename to src/tinytemplate.c index 313dc1e..4173b90 100644 --- a/tinytemplate.c +++ b/src/tinytemplate.c @@ -73,6 +73,7 @@ typedef enum { OPCODE_NEXT, OPCODE_CHLD, OPCODE_IDX, + OPCODE_BLOCK, } opcode_t; // Represents a substring of the template @@ -85,15 +86,20 @@ typedef enum { SCOPE_IF, SCOPE_IF_ELSE, SCOPE_FOR, + SCOPE_BLOCK, } scope_type_t; typedef struct { scope_type_t type; + size_t if_jcnd; size_t if_jump; - size_t for_next; + + size_t for_next; slice_t for_child_label; slice_t for_index_label; + + slice_t block_name; } scope_t; typedef struct { @@ -134,6 +140,7 @@ typedef enum { TOKEN_KWORD_FOR, TOKEN_KWORD_ELSE, TOKEN_KWORD_END, + TOKEN_KWORD_BLOCK, TOKEN_OPER_MOD, } token_t; @@ -191,6 +198,7 @@ append_instr(compile_state_t *state, case OPCODE_GETS: case OPCODE_PUSHV: case OPCODE_PUSHS: + case OPCODE_BLOCK: instr->operands[0].as_size = va_arg(operands, size_t); instr->operands[1].as_size = va_arg(operands, size_t); break; @@ -372,6 +380,11 @@ next_token_kword_or_ident(scanner_t *scanner, slice_t *slice, if (!strncmp(scanner->src + offset, "else", length)) return TOKEN_KWORD_ELSE; break; + + case 5: // block + if (!strncmp(scanner->src + offset, "block", length)) + return TOKEN_KWORD_BLOCK; + break; } return TOKEN_IDENT; @@ -756,7 +769,6 @@ selection_construct_start(scanner_t *scanner, return DONE; } - static status_t iteration_construct_start(scanner_t *scanner, compile_state_t *state, @@ -812,13 +824,48 @@ iteration_construct_start(scanner_t *scanner, return DONE; } +static status_t +block_construct_start(scanner_t *scanner, + compile_state_t *state, + error_t *error) +{ + // This function is called after "{% block" is parsed + assert(scanner->src[scanner->cur-5] == 'b' + && scanner->src[scanner->cur-4] == 'l' + && scanner->src[scanner->cur-3] == 'o' + && scanner->src[scanner->cur-2] == 'c' + && scanner->src[scanner->cur-1] == 'k'); + + if (state->scope_depth == TINYTEMPLATE_MAX_SCOPE_DEPTH) { + report(error, "Scope depth limit reached"); + return ESCOPE; + } + + slice_t label; + if (next_token(scanner, &label, NULL) != TOKEN_IDENT) { + report(error, "Missing block label"); + return ESYNTAX; + } + + append_instr(state, OPCODE_BLOCK, label.offset, label.length); + + tinytemplate_status_t status; + if ((status = close_construct(scanner, error, "block")) != DONE) + return status; + + state->scope_stack[state->scope_depth].type = SCOPE_BLOCK; + state->scope_stack[state->scope_depth].block_name = label; + state->scope_depth++; + return DONE; +} + static void resolve_scope(compile_state_t *state) { assert(state->scope_depth > 0); scope_t *scope = state->scope_stack - + state->scope_depth - 1; + + state->scope_depth-1; switch (scope->type) { @@ -841,6 +888,17 @@ resolve_scope(compile_state_t *state) instr = state->program + scope->if_jump; instr->operands[0].as_size = state->num_instr; break; + + case SCOPE_BLOCK: + { + // Get parent block name + slice_t parent_label = {0, 0}; + for (int i = state->scope_depth-2; i >= 0; i--) + if (state->scope_stack[i].type == SCOPE_BLOCK) + parent_label = state->scope_stack[i].block_name; + append_instr(state, OPCODE_BLOCK, parent_label.offset, parent_label.length); + break; + } } state->scope_depth--; @@ -900,6 +958,10 @@ construct_else(scanner_t *scanner, case SCOPE_FOR: report(error, "Bad {%% else %%} coupled with {%% for .. %%}"); return ESEMANT; + + case SCOPE_BLOCK: + report(error, "Bad {%% else %%} coupled with {%% block .. %%}"); + return ESEMANT; } return DONE; @@ -918,7 +980,7 @@ control_flow_block(scanner_t *scanner, case TOKEN_KWORD_FOR: return iteration_construct_start(scanner, state, error); case TOKEN_KWORD_END: return construct_end(scanner, state, error); case TOKEN_KWORD_ELSE: return construct_else(scanner, state, error); - + case TOKEN_KWORD_BLOCK: return block_construct_start(scanner, state, error); default: report(error, "Bad token [%.*s] after [{%%]", (int) slice.length, scanner->src + slice.offset); @@ -1050,13 +1112,28 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp, tinytemplate_value_t stack[TINYTEMPLATE_MAX_EXPR_DEPTH]; size_t stack_depth = 0; + slice_t label = {0, 0}; + bool done = false; int index = 0; while (!done) { const tinytemplate_instr_t *instr = &program[index++]; switch (instr->opcode) { - case OPCODE_NOPE: /* Do nothing */ break; - case OPCODE_DONE: done = true; break; + + case OPCODE_NOPE: + /* Do nothing */ + break; + + case OPCODE_DONE: + done = true; + break; + + case OPCODE_BLOCK: + label = (slice_t) { + .offset = instr->operands[0].as_size, + .length = instr->operands[1].as_size, + }; + break; case OPCODE_ITER: assert(stack_depth > 0); // ITER excepts a value on the stack @@ -1233,7 +1310,8 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp, { size_t offset = instr->operands[0].as_size; size_t length = instr->operands[1].as_size; - callback(userp, src + offset, length); + callback(userp, src + label.offset, label.length, + src + offset, length); break; } @@ -1248,7 +1326,8 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp, char text[128]; int num = snprintf(text, sizeof(text), "%lld", stack[stack_depth-1].as_int); assert(num > 0); - callback(userp, text, (size_t) num); + callback(userp, src + label.offset, label.length, + text, (size_t) num); break; } @@ -1257,13 +1336,15 @@ tinytemplate_eval(const char *src, const instr_t *program, void *userp, char text[128]; int num = snprintf(text, sizeof(text), "%lf", stack[stack_depth-1].as_float); assert(num > 0); - callback(userp, text, (size_t) num); + callback(userp, src + label.offset, label.length, + text, (size_t) num); break; } case TINYTEMPLATE_TYPE_STRING: - callback(userp, stack[stack_depth-1].as_string.str, - stack[stack_depth-1].as_string.len); + callback(userp, src + label.offset, label.length, + stack[stack_depth-1].as_string.str, + stack[stack_depth-1].as_string.len); break; default: diff --git a/tinytemplate.h b/src/tinytemplate.h similarity index 97% rename from tinytemplate.h rename to src/tinytemplate.h index 54ba5a1..9cd60f0 100644 --- a/tinytemplate.h +++ b/src/tinytemplate.h @@ -29,7 +29,7 @@ typedef union tinytemplate_value_t tinytemplate_value_t; typedef bool (*tinytemplate_nextcallback_t)(void*, tinytemplate_type_t*, tinytemplate_value_t*); typedef bool (*tinytemplate_getter_t)(void*, const char*, size_t, tinytemplate_type_t*, tinytemplate_value_t*); -typedef void (*tinytemplate_callback_t)(void *userp, const char *str, size_t len); +typedef void (*tinytemplate_callback_t)(void *userp, const char *lbl, size_t lblen, const char *str, size_t len); typedef struct { void *data; diff --git a/test.html b/test.html deleted file mode 100644 index c321c70..0000000 --- a/test.html +++ /dev/null @@ -1,1236 +0,0 @@ - - - - - Scrivere web server - v0.2 - - - - -
- << Home -
-

Scrivere un server TCP

- -

Indice

- - -

Introduzione

-

- In questo post spiegherò come scrivere un server TCP e, per mostrarne il funzionamento, il rispettico client. -

- -

Cos'è TCP?

-

- TCP è un protocollo di rete, ossia un protocollo che permette lo scambio di messaggi tra computer. Più nel dettaglio quello che ci permette di fare è collegare virtualmente due computer e trasferire un insieme di byte da uno all'altro. Il collegamento è virtuale perchè in realtà i computer si suppongono già fisicamente collegati mediante un insieme di router, tuttavia è solo quando entrambi manifestano l'intento di voler comunicare che questo può avvenire. Quindi per "virtuale" intendo dire che il collegamento è un'astrazione perchè di fatto i computer sono sempre stati collegati. -

- -

Come funziona?

-

- Per poter comunicare usando TCP, si deve prima decidere chi dei due nodi è il server e chi è il client. Il server è quello che si mette in ascolto per la connessione, mentre il client è colui che decide quando comunicazione deve cominciare. È da notare che la differenza tra server e client non è legata a chi invia e chi riceve informazioni, è solo un modo per gestire il primo collegamento. Se non ci fosse questa distinzione di ruoli allora sarebbe quasi impossibile creare connessioni TCP! Supponiamo che i ruoli siano simmetrici e che la connessione si avvii quando entrambi allo stesso tempo decidono di aprirla: quali sono le probabilità che due utenti ed i rispettivi computer si colleghino allo stesso tempo? Per farlo in modo preciso sarebbe richiesto qualche tipo di sincronizzazione, ma questa implicherebbe una comunicazione, tuttavia per ipotesi i computer non stanno ancora comunicando!! Un analogia che potrebbe mostrare questo problema sotto un'altra luce è quella dei telefoni cellulari. In effetti ogni volta che abbiamo addosso il cellulare ci stiamo comportando da server, perchè in ogni istante siamo aperti a ricevere telefonate. Dall'altra parte un nostro amico che ci chiama si comporta da client poichè è lui che decide di avviare la comunicazione. Rimuovere questi due ruoli comporterebbe che per parlare a telefono sia noi che il nostro amico dovremmo premere il tasto verde di chiamata allo stesso tempo. -

-

- Per il protocollo TCP ogni computer su una rete è caratterizzato da un identificativo univoco chiamato indirizzo IP. In più su ciascun PC ogni programma è caratterizzato da un ulteriore identificativo chiamato porta univoco localmente. Naturalmente due computer per parlarsi hanno bisogno dei rispettivi IP, tuttavia quelli che parlano fra di loro sono i programmi in esecuzione sui due PC, quindi c'è bisogno della porta come ulteriore fattore discriminante. Per questo motivo per avviare la comunicazione il client deve conoscere il "nome" del server, cioè la coppia indirizzo-porta. Quando il client contatterà il server, automaticamente questo verrà a conoscenza degli identificativi del client. Questo comporta che il client debba conoscere a priori l'indirizzo e la porta del server! Questo però nella pratica rappresenta un vincolo molto poco limitante. -

-

- Gli indirizzi IP sono stringhe di 32 cifre binarie (bit). Le combinazioni di 0 ed 1 (i bit) che si possono fare con una stringa di questa lunghezza sono circa 4 miliardi, per cui questo è il limite di computer che si possono avere su una rete. Per quanto riguarda le porte, queste sono stringhe binarie di 16 cifre. Le permutazioni che invece si possono ottenere in questo caso sono 65536. Quando si programma di solito le porte, dato che assumono valori piccoli (rispetto agli indirizzi IP), vengono riportate come numero (cioè in base 10 invece che base 2). Per quanto riguarda gli indirizzi IP invece, riportarle come numeri risulterebbe scomodo dato che è difficile distinguere numeri molto grandi ad occhio. Per questo motivo si usa la notazione dot-decimal, per la quale la stringa di 32 bit viene divisa in 4 stringhe da 8 e ciascuna sotto-stringa viene rappresentata in base 10 separata dalle altre con un puntino. Indirizzi IP espressi usando questa notazione sono molto comuni e chiunque abbia usato un computer ne avrà visto uno. Un esempio di indirizzo IP in notazione dot-decimal è 192.168.0.1. Dato che una stringa di 8 bit ha 256 permutazioni, i 4 numeri nella notazione dot-decimal possono solo assumere valori da 0 a 255 (i numeri da 0 a 255 sono in totale 256, cioè di conta pure lo 0). -

-

- Una volta avviata la comunicazione, i due processi mandano messaggi ed attendono risposte, sincronizzandosi, effettuando elaborazioni e producendo risultati grazie a questa cooperazione. Una volta conclusa la comunicazione, entrambi i processi possono chiudere la connessione. -

-

- Queste sono solo parole, noi dobbiamo farlo in codice tutto questo!! Me non temete! Ogni passo sarà accuratamente ed amorevolmente documentato :^) <3 -

- -

Cosa realizzeremo

-

- In verità dire che faremo un server ed un client TCP non è una descrizione esaustiva. TCP descrive solo il metodo che i programmi useranno per comunicare, ma non cosa si diranno! In particolare quel che faremo è un client che invia un messaggio al server, che leggerà il messaggio, ne convertirà maiuscole in minuscole e viceversa, e poi rimanderà la versione elaborata del messaggio. -

- -

Come lo realizzeremo: I socket

-

- Per realizzare un'applicazione del genere, dovremo fare quella che viene chiamata socket programming, cioè la programmazione che usa i "socket". -

-

- Un socket è una struttura dati del kernel della quale possiamo chiamare dei metodi per effettuare delle comunicazioni sulla rete. È il modo in cui il sistema operativo astrae le funzionalità più crude dell'hardware. Il tema dell'astrazione dell'hardare è molto vasto, ma per i nostri scopi ci basta questo accenno. -

-

- Il client avrà una struttura del tipo -

-
-
- - - - - - - - - - - - - - - - - - - -
1main()
2{
3 address = 127.0.0.1
4 port = 8080
5 socket = create_tcp_socket()
6
7 connect(socket, address, port)
8
9 messaggio = "Ossimoro"
10
11 send(socket, messaggio)
12
13 messaggio = receive(socket)
14
15 print('Il server ha risposto con: ' + messaggio)
16
17 close(socket)
18}
-
-
- -

- mentre il server: -

-
-
- - - - - - - - - - - - - - - - - - - - - -
1main()
2{
3 port = 8080
4 socket = create_tcp_socket()
5
6 listen(socket, port)
7
8 loop {
9 socket2 = accept(socket)
10
11 messaggio = read(socket2)
12
13 messaggio = convert_case(messaggio)
14
15 send(socket2, messaggio)
16
17 close(socket2)
18 }
19 close(socket)
20}
-
-
- -

Socket

-

- I socket possono svolgere tante funzioni, quindi quando ne creiamo uno dobbiamo specificare le modalità di utilizzo. La funzione che permette di creare un socket è -

-
-
- - - - -
1#include <sys/socket.h>
2
3int socket(int domain, int type, int protocol);
-
-
- - -

- Con questa notazione include + prototipo della funzione intendo dire che la libreria inclusa definisce la funzione sotto. -

- -

- Il modo in cui si usa questa funzione è un po' caotico. Questa cosa è dovuta al fatto che quando ne fu progettata l'interfaccia, si cercò di prevedere gli sviluppi futuri, che poi non avvennero mai. -

- -

- Il primo argomento domain specifica lo spazio degli indirizzi del protocollo che vogliamo usare. Il valore di questo parametro può essere specificato usando dei valori specificati in sys/socket.h come AF_INET, AF_UNIT oppure AF_BLUETOOTH. Il prefisso AF_ sta per Address Family. Noi useremo solo AF_INET, in cui INET sta, banalmente, per internet. -

- -

- Il secondo argomento type specifica quello che comunemente indichiamo col nome di protocollo, cioè TCP nel nostro caso. Il valore che dobbiamo fornire per TCP è SOCK_STREAM. Altri esempi di protocolli che possiamo specificare sono UDP (SOCK_DGRAM) o l'assenza di protocollo (SOCK_RAW). -

- -

- Il terzo valore protocol è superfluo. Nel caso di TCP può sempre essere zero. -

- -

- La funzione socket ritorna quel che è comunemente chiamato descrittore del socket, cioè un numero intero positivo che descrive inequivocabilmente il nostro socket all'interno del kernel. Ogni volta che vorremo operare sul socket, forniremo alle funzione questo descrittore ed il sistema operativo saprà su quale socket operare. Se la creazione della struttura fallisce, allora un valore negativo è ritornato. -

- -

- In sintesi, per creare un socket TCP faremo una cosa del tipo: -

-
-
- - - - - - - - - - - - - - - - - -
1#include <unistd.h> // Questa definisce [close]
2#include <sys/socket.h>
3
4int main(void)
5{
6 int fd = socket(AF_INET, SOCK_STREAM, 0);
7 if(fd < 0) {
8 // Non sono riuscito a creare il socket TCP!
9 return -1;
10 }
11
12 // .. fai cose col socket ..
13
14 close(fd); // Quando abbiamo finito, possiamo chiuderlo.
15 return 0;
16}
-
-
- -

- Su linux ed i sistemi unix in generale, le risorse sono spesso astratte sotto il concetto di file. I socket sarebbero un tipo speciale di file. Per questo motivo il descrittore dei socket è anche chiamato file descriptor (e da questo il nome fd della variabile) -

- -

- Sia nel caso del client che del server l'apertura e chiusura del socket sono uguali. Quello che cambia è la loro configurazione e poi connessione. Una volta avviata invece il codice torna simmetrico, nel senso che i due programmi possono ricevere ed inviare dati allo stesso modo. -

- -

- Configurazione del socket per il server -

-

- Quel che il server dovrà fare dopo aver creato il socket è assegnargli un indirizzo IP tra quelli che ha a disposizione (potrebbe evere più di una interfaccia di rete!). Questo si fa usando la funzione bind, infatti "bind" si potrebbe tradurre dall'inglese all'italiano con "legare" (il socket è legato all'indirizzo). Una volta fatto questo è possibile attendere la connessione del client usando la funzione listen, che "ascolta" per connessioni ("listen" è la parola inglese che corrisponde ad "ascoltare" in italiano). Per accettare le connessioni dopo aver fatto listen, il server userà la funzione accept, che restituirà un nuovo socket relativo alla particolare connessione appena creata. -

- -

Bind

-

- La funzione bind è la parte più difficile della guida, quindi una volta fatta quella sarà tutto in discesa! L'interfaccia della funzione è questa qui: -

- -
-
- - - - -
1#include <sys/socket.h>
2
3int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-
-
- -

- Ad un livello più alto, quello che fa bind è prendere un buffer contenente un indirizzo ed associarlo ad un socket. Dato che questa funzione si può usare per più protocolli con spazi di indirizzi diversi, fa il minimo numero di assunzioni su come sia fatto un indirizzo. Infatti, la struttura che rappresente un indirizzo generico per bind è questa qui -

- -
-
- - - - - - - - - - -
1#include <sys/socket.h>
2
3typedef unsigned short sa_family_t;
4// [sa_family_t] contiene i valori [AF_*]
5
6struct sockaddr {
7 sa_family_t sa_family;
8 char sa_data[14];
9};
-
-
- -

- in cui l'effettivo valore dell'indirizzo è un array di byte. Programmando in C, interpretare una struttura dati come array di caratteri corrisponde a dire "non mi interessa sapere come è strutturato questo dato, voglio solo poterlo spostare in giro". L'indirizzo effettivo poi potrebbe anche essere meno o più grande di struct sockaddr, da cui la necessita dell'argomento addrlen di bind in cui è possibile specificare la dimensione della regione puntata dall'argomento addr. -

- -

- Se questa interfaccia ti sembra confusa, non temere! È quel che provano tutti. È il risultato di anni di standard e convenzioni che hanno avuto bisogno di essere sempre retrocompatibili. -

- -

- Tuttavia, quando andremo a costruire l'indirizzo da fornire a bind non opereremo su una struttura del tipo struct sockaddr ma di tipo struct sockaddr_in, definita come -

- -
-
- - - - - - - - - - - - - -
1#include <netinet/in.h>
2
3struct sockaddr_in {
4 short sin_family;
5 unsigned short sin_port;
6 struct in_addr sin_addr;
7 char sin_zero[8];
8};
9
10struct in_addr {
11 unsigned long s_addr;
12};
-
-
- -

- il cui layout è compatibile a struct sockaddr (entrambi hanno fin_family allo stesso posto e le loro dimensioni sono uguali, di 16 byte), ma in più il campi sa_data di struct sockaddr è esploso nei tre campo sin_port, sin_addr e sin_zero. Una volta configurata questa struttura potremo fornirla a bind dopo aver fatto un cast a struct sockaddr. -

- -

- Il campo sin_family di struct sockaddr (e quindi di struct sockaddr_in) contiene il tipo di indirizzo, quindi uno di quegli identificativi che cominciano con AF_. Il valore di questo campo deve essere uguale al primo argomento di socket, cioè AF_INET. Del resto ha senso interpretare struct sockaddr come un struct sockaddr_in solo quando usiamo AF_INET. Il campo sin_family di un struct sockaddr_in sarà sempre AF_INET. -

- -

- I campi sin_port e sin_addr (più in particolare sin_addr.s_addr) sono rispettivamente porta ed indirizzo, cioè gli stessi porta ed indirizzo di cui parlavamo nell'introduzione al TCP. Questi due campi dovranno avere l'ordinamento dei byte della rete (cioè big endian, nel caso del TCP), quindi se il nostro computer non ha lo stesso suo ordinamento (cioè è little endian) allora dovremo effettuare una conversione. Per effettuare questa conversione comodamente, possiamo usare le funzioni -

- -
-
- - - - - - -
1#include <arpa/inet.h>
2uint32_t htonl(uint32_t hostlong);
3uint16_t htons(uint16_t hostshort);
4uint32_t ntohl(uint32_t netlong);
5uint16_t ntohs(uint16_t netshort);
-
-
- - -

- Che trasformano interi da ordinamento dell'host (il nostro computer) a quello della rete o viceversa. Infatti "hton" ed "ntoh" stanno per "host to network" e "network to host". La "l" o "s" finali invece fanno riferimento al tipo di dato che convertono, cioè "long" o "short". Nel caso dell'indirizzo dovremo usare htonl, mentre nel caso della porta htons. -

- -

- Invece di specificare un singolo indirizzo IP, possiamo usare la costante INADDR_ANY - definita in arpa/inet.h per effettuare il bind su tutti i possibili indirizzi disponibili. -

- -

- L'ultimo campo sin_zero ha come unica funzione quella di far combaciare la dimensione delle strutture sockaddr e sockaddr_in. Infatti il nome stesso contiene la parola "zero" per indicare che questo campo dovrebbe solo errere posto uguale a zero. -

- -

- Il valore di ritorno di bind è zero quando tutto è andato a buon fine ed un valore negativo quando ha fallito. -

- -

- Detto questo, il binding del server sarà fatto in questo modo qui -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1#include <string.h> // memset
2#include <unistd.h> // Questa definisce [close]
3#include <sys/socket.h>
4#include <arpa/inet.h>
5#include <netinet/in.h>
6
7int main(void)
8{
9 int fd = socket(AF_INET, SOCK_STREAM, 0);
10 if(fd < 0) {
11 // Non sono riuscito a creare il socket TCP!
12 return -1;
13 }
14
15 struct sockaddr_in addr;
16 addr.sin_family = AF_INET;
17 addr.sin_port = htons(8080);
18 addr.sin_addr.s_addr = INADDR_ANY;
19 memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
20
21 if(bind(fd, (struct sockaddr*) &addr,
22 sizeof(struct sockaddr_in))) {
23 // Il binding è fallito!!
24 close(fd);
25 return -1;
26 }
27
28 // .. fai cose col socket ..
29
30 close(fd); // Quando abbiamo finito, possiamo chiuderlo.
31 return 0;
32}
-
-
- -

- Decisamente più facile a farsi che a dirsi!! -

- -

- Come per AF_INET, le altre famiglie di indirizzi rappresentano a loro modo il contenuto di struct sockaddr. Per questo motivo ciascuna definisce una propria struttura analoga a struct sockaddr_in per costruire i propri indirizzi. Ad esempio per AF_INET6 (anche noto come IPv6) si usa sockaddr_in6, mentre per AF_UNIX (i socket unix) si usa struct sockaddr_un. Tuttavia queste strutture potrebbero non avere la stessa dimensione di struct sockaddr! Questo è dovuto al fatto che quando è stata progettata questa API originariamente si è supposto che 14 byte sarebbero bastati per ogni genere di indirizzo. Quando poi è risultato necessario avere indirizzi più grandi, si è preferito non cambiare la definizione di struct sockaddr per rimanere retrocompatibili. In ogni caso questa differenza di dimensione non crea problemi di correttezza nei programmi. -

- -

Listen

-

- Ultimo passo dell'inizializzazione è il listening, cioè effettivamente ascoltare per nuove connessioni. La funzione che dobbiamo usare è -

- -
-
- - - - -
1#include <sys/socket.h>
2
3int listen(int sockfd, int backlog);
-
-
- - -

- Il primo argomento sockfd naturalmente è il socket che vogliamo mettere in ascolto, mentre il secondo backlog corrisponde alla dimensione della coda di connessioni non ancora accettate. Il valore di ritorno, come per bind, è non-zero quando qualcosa va storto. -

- -

- Ogni volta che una richiesta di connessione viene ricevuta mentre il programma è in ascolto, il kernel la mette in una coda. Il nostro programma dal lato suo prenderà elementi da quella coda usando la funzione accept. Il paramentro backlog fa riferimento alla dimensione di queste coda. Se una nuova connessione arriva ma la code è piena, sarà automaticamente rifiutata, per questo è importante scegliere accuratamente questo valore. Se questo parametro è troppo piccolo ed il programma non riesce ad accettare connessioni con una frequenza comparabile a quella con cui arrivano, allora delle connessioni saranno perse. Se invece lo scegliamo troppo grande, delle risorse saranno sprecate. -

- -

- Naturalmente per condizioni di prova come la nostra ha poca importanza che valore usiamo. Anche scegliere 1 andrà bene, tuttavia portando questo programma in circostanze più realistiche, questo creerebbe problemi! -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1#include <string.h> // memset
2#include <unistd.h> // Questa definisce [close]
3#include <sys/socket.h>
4#include <arpa/inet.h>
5#include <netinet/in.h>
6
7int main(void)
8{
9 int fd = socket(AF_INET, SOCK_STREAM, 0);
10 if(fd < 0) {
11 // Non sono riuscito a creare il socket TCP!
12 return -1;
13 }
14
15 struct sockaddr_in addr;
16 addr.sin_family = AF_INET;
17 addr.sin_port = htons(8080);
18 addr.sin_addr.s_addr = INADDR_ANY;
19 memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
20
21 if(bind(fd, (struct sockaddr*) &addr,
22 sizeof(struct sockaddr_in))) {
23 // Il binding è fallito!!
24 close(fd);
25 return -1;
26 }
27
28 if(listen(fd, 32)) {
29 // Non sono riuscito ad ascoltare!
30 close(fd);
31 return -1;
32 }
33
34 // .. fai cose col socket ..
35
36 close(fd); // Quando abbiamo finito, possiamo chiuderlo.
37 return 0;
38}
-
-
- -

Accept

-

- Una volta completata la configurazione, il server potrà accettare nuove connessioni, usarle e poi chiuderle iterativamente. Come accennato prima, per accettare nuove richiesta si usa -

- -
-
- - - - - -
1#include <sys/socket.h>
2
3int accept(int sockfd, struct sockaddr *restrict addr,
4 socklen_t *restrict addrlen);
-
-
- -

- dove sockfd è il descrittore del socket messo in ascolto mentre addr e addrlen sono argomenti di output che restituiscono l'indirizzo del client in una struttura del tipo struct sockaddr_in. Se non siamo interessati all'indirizzo possiamo fornire NULL ai due argomenti finali. Il valore di ritorno invece è il descrittore di un nuovo socket dal quale si potranno leggere e scrivere byte. Una volta conclusa la comunicazione con questo client, questo socket potrà essere chiuso ed una nuova connessione accettata usando dinuovo accept. Naturalmente è anche possibile accettare più connessioni allo stesso tempo chiamando accept più volte in sequenza prima, ma questo ci costringerebbe a dover rendere decisamente più sofisticata la struttura del nostro programma. -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1#include <string.h> // memset
2#include <unistd.h> // Questa definisce [close]
3#include <sys/socket.h>
4#include <arpa/inet.h>
5#include <netinet/in.h>
6
7int main(void)
8{
9 int fd = socket(AF_INET, SOCK_STREAM, 0);
10 if(fd < 0) {
11 // Non sono riuscito a creare il socket TCP!
12 return -1;
13 }
14
15 struct sockaddr_in addr;
16 addr.sin_family = AF_INET;
17 addr.sin_port = htons(8080);
18 addr.sin_addr.s_addr = INADDR_ANY;
19 memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
20
21 if(bind(fd, (struct sockaddr*) &addr,
22 sizeof(struct sockaddr_in))) {
23 // Il binding è fallito!!
24 close(fd);
25 return -1;
26 }
27
28 if(listen(fd, 32)) {
29 // Non sono riuscito ad ascoltare!
30 close(fd);
31 return -1;
32 }
33
34 while(1) {
35 int clifd = accept(fd, NULL, NULL);
36 if(clifd < 0)
37 continue; // Torna in cima al loop
38
39 // .. fai cose col socket ..
40
41 close(clifd);
42 }
43
44 close(fd); // Quando abbiamo finito, possiamo chiuderlo.
45 return 0;
46}
-
-
- -

- Configurazione del socket per il client -

- -

- La configurazione del client è più semplice del server. Come il server crea un socket TCP usando socket, poi però si connette al server chiamando la funzione connect. Se connect ha avuto buon fine, la connessione è stata stabilita ed è possibile comunicare. -

- -

Connect

-

- La funzione connect è definita in questo modo qui -

- -
-
- - - - - -
1#include <sys/socket.h>
2
3int connect(int sockfd, const struct sockaddr *addr,
4 socklen_t addrlen);
-
-
- -

- Dove sockfd è il socket che vogliamo usare per effettuare la connessione (quello creato con socket) e la coppia addr/addrlen specifica l'indirizzo al quale vogliamo connetterci. Come per gli altri caso avremo addr pari ad un struct sockaddr_in e addrlen pari a sizeof(struct sockaddr_in). Se la funzione fallisce, allora -1 viene ritornato, altrimenti 0. -

-

- L'inizializzazione del client quindi avrà una forma del genere -

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1#include <string.h> // memset
2#include <unistd.h> // Questa definisce [close]
3#include <sys/socket.h>
4#include <arpa/inet.h>
5#include <netinet/in.h>
6
7int main(void)
8{
9 int fd = socket(AF_INET, SOCK_STREAM, 0);
10 if(fd < 0) {
11 // Non sono riuscito a creare il socket TCP!
12 return -1;
13 }
14
15 struct sockaddr_in addr;
16 addr.sin_family = AF_INET;
17 addr.sin_port = htons(8080); // Questa è la stessa del server!!
18 addr.sin_addr.s_addr = ???; // Ma qui cosa ci và?!
19 memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
20
21 if(connect(fd, (struct sockaddr*) &addr,
22 sizeof(struct sockaddr_in))) {
23 // La connessione è fallita!!
24 close(fd);
25 return -1;
26 }
27
28 // .. fai cose col socket ..
29
30 close(fd); // Quando abbiamo finito, possiamo chiuderlo.
31 return 0;
32}
-
-
- -

- L'indirizzo che forniamo a connect deve avere la stessa porta sulla quale il server ha fatto bind e come indirizzo IP anche quello sul quale ha fatto bind. Se il server ha fatto bind su più di un indirizzo IP usando INADDR_ANY, ci basta specificare uno di quelli a sua disposizione. -

- -

- Normalmente gli indirizzi IP sono noti in rappresentazione dotted decimal. In tal caso per convertirli da tale rappresentazione ad un intero con i byte ordinati come piace alla rete, si può usare la funzione inet_pton: -

- -
-
- - - - - -
1#include <arpa/inet.h>
2
3int inet_pton(int af, const char *restrict src,
4 void *restrict dst);
-
-
- - -

- L'argomento af è la famiglia di indirizzi, ossia AF_INET nel nostro caso. Invece src è la stringa (zero-terminata) contenente l'indirizzo in rappresentazione dotted decimal. L'argomento dst è il riferimento ad una struttura struct in_addr dove vogliamo che la funzione scriva l'indirizzo generato. Se tutto va bene, allora la funzione ritorna 1, altrimenti 0 o -1. -

- -

- La funzione inet_pton può operare anche su indirizzi IPv6. In tal caso l'argomento af è pari a AF_INET6 e dst punterà ad una struttura di tipo struct in_addr6. È per questo motivo che dst ha tipo void*, perchè può essere sia di tipo struct in_addr che struct in_addr6. -
- Esistono molte funzioni che effettuano questo genere di conversione. Un altro esempio è inet_aton, che però converte solo indirizzi IPv4. -

- -

- Dato che sia client che server saranno eseguiti sullo stesso computer, possiamo considerare l'indirizzo IP del server pari a 127.0.0.1, quindi la connessione diventerà -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1#include <string.h> // memset
2#include <unistd.h> // Questa definisce [close]
3#include <sys/socket.h>
4#include <arpa/inet.h>
5#include <netinet/in.h>
6
7int main(void)
8{
9 int fd = socket(AF_INET, SOCK_STREAM, 0);
10 if(fd < 0) {
11 // Non sono riuscito a creare il socket TCP!
12 return -1;
13 }
14
15 const char ip[] = "127.0.0.1";
16 unsigned short port = 8080;
17
18 struct sockaddr_in addr;
19 addr.sin_family = AF_INET;
20 addr.sin_port = htons(port);
21 memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
22
23 if(inet_pton(AF_INET, ip, &addr.sin_addr) != 1) {
24 // Non sono riuscito a convertire l'indirizzo IP!!
25 close(fd);
26 return -1;
27 }
28
29 if(connect(fd, (struct sockaddr*) &addr,
30 sizeof(struct sockaddr_in))) {
31 // La connessione è fallita!!
32 close(fd);
33 return -1;
34 }
35
36 // .. fai cose col socket ..
37
38 close(fd); // Quando abbiamo finito, possiamo chiuderlo.
39 return 0;
40}
-
-
- -

- A questo punto anche la configurazione del client è conclusa! -

- -

La business logic

-

- Una volta connessi client e server, sarà il client a mandare il primo messaggo, quindi la prima cosa che farà il server dopo la connessione (cioè l'accept) è una chiamata a recv (dall'inglese, "ricevi"), mentre il client dopo la connessione (connect) chiamerà send (dall'inglese, "invia"). -

- -

Send

-

- La funzione send è definita così -

- -
-
- - - - -
1#include <sys/socket.h>
2
3ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-
-
- -

- Dove sockfd è il socket relativo alla connessione (quello ritornato da accept nel server, oppure quello ritornato da socket nel client). Gli argomenti buf e len fanno riferimento all buffer che deve essere inviato e quanto è grande. Infine flags è un argomento che permette di configurare il modo in cui viene effettuato l'invio (per saperne di più sui flags, leggi questo). Il valore di default di flags è 0, ossia quel che useremo noi. Il valore di ritorno invece è -1 se qualcosa è andato storto, oppure il numero di byte inviati. È possibile che il valore di ritorno sia non negativo ma inferiore alla dimensione del buffer, quindi solo una parte del buffer è stata inviata, in tal caso dovremmo manualmente ritentare l'invio della parte mancante! -

- -

- La funzione send, quando l'argomento flags è posto a 0, è equivalente alla funzione write. La funzione send opera solo sui socket, mentre write opera sui file in generale (un socket è un tipo di file). -
-
- Il tipo ssize_t è una versione con segno di size_t (cioè può assumere valori negativi). Questi tipi di dato sono usati di solito per mantenere la dimensione di regioni di memoria. -

- -

Recv

-

- La funzione recv è abbastanza simmetrica rispetto alla sorella send. L'interfaccia è questa qui: -

-
-
- - - - -
1#include <sys/socket.h>
2
3ssize_t recv(int sockfd, void *buf, size_t len, int flags);
-
-
- - -

- Anche qui sockfd è il socket della connessione, tuttavia il buffer buff con dimensione len non sarà letto ma scritto. Il valore di len è considerato più come il numero massimo di byte da leggere, infatti il valore di ritorno, che è il numero di byte ricevuti, può solo essere inferiore o uguale a len. Tuttavia, in caso di errore è ritornato -1. Per quanto riguada il parametro flags, il comportamento è analogo a send. -

- -

- Una cosa aggiuntiva da notare è che quando recv ritorna 0 significa che il nodo col quale siamo in comunicazione si è disconnesso. -

- -

- La relazione fra send e write si ha anche nel caso di recv e read. -

- -

- La business logic del client -

- -

- Per quanto riguarda il client, un messaggio che verrà mandato al server per essere convertito. Quando la risposta sarà ricevuta, il programma la stampera a video. Avremo una cosa del genere (ho rimosso il codice che abbiamo scritto sino ad ora per poterci concetrare su quello che dobbiamo fare ora) -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1/* ..gli header qui.. */
2#include <stdio.h>
3
4ssize_t super_send(int fd, const char *buf, size_t len, int flags)
5{
6 ssize_t sent_bytes = 0;
7 do {
8 ssize_t n = send(fd, buf + sent_bytes,
9 len - sent_bytes, flags);
10 if(n < 0) {
11 sent_bytes = -1;
12 break;
13 }
14 sent_bytes += n;
15 } while((size_t) sent_bytes < len);
16 return sent_bytes;
17}
18
19ssize_t super_recv(int fd, char *buf, size_t len, int flags)
20{
21 ssize_t received_bytes = 0;
22 do {
23 ssize_t n = recv(fd, buf + received_bytes,
24 len - received_bytes, flags);
25 if(n <= 0) {
26 received_bytes = n;
27 break;
28 }
29 received_bytes += n;
30 } while((size_t) received_bytes < len);
31 return received_bytes;
32}
33
34int main(void)
35{
36 int fd = /* ..creazione del socket.. */
37
38 /* ..inizializzazione del socket.. */
39
40 const char *message = "Ossimoro";
41
42 char risposta[32]; // Il buffer che conterrà la risposta del server.
43
44 // Assumiamo che la lunghezza massima della risposta
45 // sia 31 byte dato che deve entrare nel buffer
46 // [risposta] (31 perchè dobbiamo aggiungere un byte
47 // nullo alla fine per rendere la risposta una
48 // stringa zero-terminata).
49
50 // Dato che la risposta ha la stessa lunghezza del
51 // nostro messaggio, possiamo assicurarci già ora
52 // che la risposta non sforerà il buffer.
53 size_t message_len = strlen(message);
54 if(message_len > sizeof(risposta)-1) { // NOTA: sizeof(risposta)-1 è 31
55 fprintf(stderr, "Il messaggio non può essere "
56 "più lungo di %ld caratteri\n", sizeof(risposta)-1);
57 close(fd);
58 return -1;
59 }
60
61 // Invia il messaggio!
62 ssize_t n = super_send(fd, message, message_len, 0);
63 if(n < 0) {
64 /* Qualcosa è andato storto! */
65 fprintf(stderr, "Non sono riuscito ad inviare [%s]\n", message);
66 close(fd);
67 return -1;
68 }
69
70 n = super_recv(fd, risposta, message_len, 0);
71 if(n < 0) {
72 /* Qualcosa è andato storto! */
73 fprintf(stderr, "La ricezione della risposta a [%s] è fallita!", message);
74 close(fd);
75 return -1;
76 }
77
78 // A questo punto [recv] avrà scritto esattamente [n] byte
79 // all'interno di [risposta], per cui il primo byte dopo il
80 // messaggio è proprio alla posizione [risposta[n]]. Ora
81 // possiamo aggiungere il byte nullo terminatore:
82 risposta[n] = '\0';
83
84 // E stampare il messaggio
85 printf("[%s] -> [%s]\n", message, risposta);
86
87 /* ..chiudi il socket.. */
88 return 0;
89}
-
-
- -

- In realtà in questo codice abbiamo barato un po'. Non è necessariamente vero che recv e send inviino e ricevano l'intero messaggio con una sola chiamata. Per inviare il messaggio potrebbero servire due o più send! La necessità di chiamare iterativamente queste funzioni sorge quando il loro valore di ritorno (cioè n in questo esempio) è positivo ma comunque inferiore alla lunghezza del messaggio che abbiamo inviato. In questo programma non è un problema grave, perchè nel peggiore delle ipotesi risulterà che il messaggio del server è corretto a meno di qualche byte finale mancante. -

- -

- Per rendere il nostro programma più robusto, la send potrebbe essere chiamata in questo modo qui -

-
-
- - - - - - - - - - - - - -
1ssize_t sent_bytes = 0;
2do {
3 // [message[i] + sent_bytes] è l'indirizzo della parte
4 // del messaggio non ancora inviato, mentre la sua
5 // lunghezza è [message_len - sent_bytes].
6 ssize_t n = send(fd, messages[i] + sent_bytes, message_len - sent_bytes, 0);
7 if(n < 0) {
8 sent_bytes = -1;
9 break;
10 }
11 sent_bytes += n;
12} while(sent_bytes < message_len);
-
-
- -

- In questo modo send verrà chiamata finchè l'interò messaggio sarà stato inviato, oppure un errore sarà avvenuto. Questo loop nel complesso si comporta come una send dove il valore di ritorno è sent_bytes ma che se invia il messaggio, non è mai parzialmente. -

-

- Quello che potremmo fare è creare una funzione ausiliaria super_send che effettua questo meccanismo per poi sostituirla alla semplice send interna al nostro programma. -

-

- Come accennato lo stesso problema si pone per recv. È possibile che ci vogliano più chiamate per ricevere l'intero messaggio. Per risolvere questo problema, come per la send, si potrebbe aggiungere un loop attorno alla sua chiamata -

-
-
- - - - - - - - - - -
1ssize_t received_bytes = 0;
2do {
3 ssize_t n = recv(fd, risposta + received_bytes, message_len - received_bytes, 0);
4 if(n <= 0) {
5 received_bytes = n;
6 break;
7 }
8 received_bytes += n;
9} while(received_bytes < message_len);
-
-
- -

- Le stesse considerazione rispetto alla receive valgono: questo loop si comporta come una versione augmentata di recv che però non riceve mai il messaggio parzialmente, a patto che non avvenga un errore (in tal caso received_bytes == -1) e che il server non si disconnetta (received_bytes == 0). -

- -

- Il codice completo del client avendo aggiunto super_send e super_recv è -

- {% code %} -#include // memset -#include // Questa definisce [close] -#include -#include -#include -#include -ssize_t super_send(int fd, const char *buf, size_t len, int flags) -{ - ssize_t sent_bytes = 0; - do { - ssize_t n = send(fd, buf + sent_bytes, - len - sent_bytes, flags); - if(n < 0) { - sent_bytes = -1; - break; - } - sent_bytes += n; - } while((size_t) sent_bytes < len); - return sent_bytes; -} -ssize_t super_recv(int fd, char *buf, size_t len, int flags) -{ - ssize_t received_bytes = 0; - do { - ssize_t n = recv(fd, buf + received_bytes, - len - received_bytes, flags); - if(n <= 0) { - received_bytes = n; - break; - } - received_bytes += n; - } while((size_t) received_bytes < len); - return received_bytes; -} -int main(void) -{ - int fd = socket(AF_INET, SOCK_STREAM, 0); - if(fd < 0) { - // Non sono riuscito a creare il socket TCP! - return -1; - } - const char ip[] = "127.0.0.1"; - unsigned short port = 8080; - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); - - if(inet_pton(AF_INET, ip, &addr.sin_addr) != 1) { - // Non sono riuscito a convertire l'indirizzo IP!! - close(fd); - return -1; - } - if(connect(fd, (struct sockaddr*) &addr, - sizeof(struct sockaddr_in))) { - // La connessione è fallita!! - close(fd); - return -1; - } - - const char *message = "Ossimoro"; - char risposta[32]; // Il buffer che conterrà la risposta del server. - size_t message_len = strlen(message); - if(message_len > sizeof(risposta)-1) { // NOTA: sizeof(risposta)-1 è 31 - fprintf(stderr, "Il messaggio non può essere " - "più lungo di %ld caratteri\n", sizeof(risposta)-1); - close(fd); - return -1; - } - // Invia il messaggio! - ssize_t n = super_send(fd, message, message_len, 0); - if(n < 0) { - /* Qualcosa è andato storto! */ - fprintf(stderr, "Non sono riuscito ad inviare [%s]\n", message); - close(fd); - return -1; - } - n = super_recv(fd, risposta, message_len, 0); - if(n < 0) { - /* Qualcosa è andato storto! */ - fprintf(stderr, "La ricezione della risposta a [%s] è fallita!", message); - close(fd); - return -1; - } - risposta[n] = '\0'; - printf("[%s] -> [%s]\n", message, risposta); - - close(fd); // Quando abbiamo finito, possiamo chiuderlo. - return 0; -} - {% end %} -

- Decisamente un bel pezzo di programma! -

- -

- La business logic del server -

-

- Il server dalla sua parte, accetterà una connessione, riceverà il messaggio e dopo averlo convertito lo rimanderà al client. Una volta inviato tornera ad attendere per una nuova connessione. -

- {% code %} -/* ..qui gli header.. */ -#include // isupper, tolower, toupper -ssize_t super_send(int fd, const char *buf, size_t len, int flags) -{ - ssize_t sent_bytes = 0; - do { - ssize_t n = send(fd, buf + sent_bytes, - len - sent_bytes, flags); - if(n < 0) { - sent_bytes = -1; - break; - } - sent_bytes += n; - } while((size_t) sent_bytes < len); - return sent_bytes; -} -int main(void) -{ - int fd = /* .. crea il socket.. */ - /* ..inizializzalo.. */ - - while(1) { - int clifd = accept(fd, NULL, NULL); - if(clifd < 0) - /* Errore durante l'accettazione */ - continue; // Torna ad accettare richieste - - char buffer[32]; - - // In questo caso usiamo [recv] e non [super_recv] - // perchè non conosciamo la dimensione del messaggio - // a priori. - ssize_t n = recv(clifd, buffer, sizeof(buffer)-1, 0); - if(n <= 0) { - // C'è stato un errore oppure - // il client si è disconnesso. - // Chiudi il server e torna ad - // aspettare per nuove richieste. - close(clifd); - continue; - } - buffer[n] = '\0'; - /* Converti la stringa */ - for(int i = 0; buffer[i] != '\0'; i += 1) { - char c = buffer[i]; - if(isupper(c)) - c = tolower(c); - else - c = toupper(c); - buffer[i] = c; - } - - // Ed ora inviala dinuovo - super_send(clifd, buffer, n, 0); - - // Non controlliamo il valore di ritorno di - // [super_send] perchè in ogni caso chiuderemmo - // il socket. - - close(clifd); - } - - /* ..chiudi il socket.. */ - return 0; -} - {% end %} -

- Aggiungendo la porzione di inizializzazione e le altre omesse, si ottiene -

- {% code %} -#include // memset -#include // Questa definisce [close] -#include -#include -#include -#include // isupper, tolower, toupper -ssize_t super_send(int fd, const char *buf, size_t len, int flags) -{ - ssize_t sent_bytes = 0; - do { - ssize_t n = send(fd, buf + sent_bytes, - len - sent_bytes, flags); - if(n < 0) { - sent_bytes = -1; - break; - } - sent_bytes += n; - } while((size_t) sent_bytes < len); - return sent_bytes; -} -int main(void) -{ - int fd = socket(AF_INET, SOCK_STREAM, 0); - if(fd < 0) { - // Non sono riuscito a creare il socket TCP! - return -1; - } - - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(8080); - addr.sin_addr.s_addr = INADDR_ANY; - memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); - - if(bind(fd, (struct sockaddr*) &addr, - sizeof(struct sockaddr_in))) { - // Il binding è fallito!! - close(fd); - return -1; - } - if(listen(fd, 32)) { - // Non sono riuscito ad ascoltare! - close(fd); - return -1; - } - while(1) { - int clifd = accept(fd, NULL, NULL); - if(clifd < 0) - /* Errore durante l'accettazione */ - continue; // Torna ad accettare richieste - - char buffer[32]; - ssize_t n = recv(clifd, buffer, sizeof(buffer)-1, 0); - if(n <= 0) { - close(clifd); - continue; - } - buffer[n] = '\0'; - /* Converti la stringa */ - for(int i = 0; buffer[i] != '\0'; i += 1) { - char c = buffer[i]; - if(isupper(c)) - c = tolower(c); - else - c = toupper(c); - buffer[i] = c; - } - super_send(clifd, buffer, n, 0); - close(clifd); - } - close(fd); // Quando abbiamo finito, possiamo chiuderlo. - return 0; -} - {% end %} -

- Per come è stato scritto questo programma, il controllo non uscirà mai dal while, per cui l'ultima chiamata a close, in realtà, non sarà mai eseguita! Il motivo per cui l'ho lasciata è per mostrare comunque la struttura generale del programma che usa i socket. -

- -

- In realtà i nomi super_send e super_recv sono intesi come nomi umoristici, nomi più appropriati sarebbero send_all e recv_all. -

- -

Riferimenti

- -
-
- - \ No newline at end of file diff --git a/tt b/tt deleted file mode 100644 index e526c01484e9112427a79a6bbae5624289c75966..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105296 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 J3Pfd%{||T_ub%(_ diff --git a/tt.exe b/tt.exe index 11476337b2598401f2fb9652f74e6dc12c65fc31..15832371ed3dfd500f9af58d861531ba26b0c010 100644 GIT binary patch delta 51509 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 delta 49259 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