{"id":392,"date":"2010-10-20T12:00:50","date_gmt":"2010-10-20T11:00:50","guid":{"rendered":"http:\/\/www.oscene.net\/it\/?p=392"},"modified":"2010-10-20T12:07:34","modified_gmt":"2010-10-20T11:07:34","slug":"come-programmare-le-socket-in-ambienti-gnulinux-parte-2","status":"publish","type":"post","link":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2","title":{"rendered":"Come programmare le socket in ambienti GNU\/Linux (Parte 2)"},"content":{"rendered":"<p>Nel primo articolo abbiamo analizzato il funzionamento delle socket e di un server con rispettivo client. In questo vedremo un modo di programmare un tipico <strong>server concorrente<\/strong> utilizzando la funzione <strong>fork()<\/strong>.<\/p>\n<p>Prima di addentrarci nel codice del server concorrente, vediamo un po&#8217; come funziona la tecnica di <strong>forking<\/strong>.<\/p>\n<h2><strong>Forking<\/strong><\/h2>\n<div id=\"attachment_510\" style=\"width: 167px\" class=\"wp-caption alignright\"><a href=\"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-510\" class=\"size-medium wp-image-510 \" title=\"Schema del forking di un'applicazione\" src=\"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma-157x300.png\" alt=\"\" width=\"157\" height=\"300\" srcset=\"https:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma-157x300.png 157w, https:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma.png 477w\" sizes=\"(max-width: 157px) 100vw, 157px\" \/><\/a><p id=\"caption-attachment-510\" class=\"wp-caption-text\">Schema del forking di un&#39;applicazione<\/p><\/div>\n<p>Il forking consente di effettuare delle copie di un processo. Il processo che genera copie di se stesso si chiama <strong>processo padre<\/strong>, mentre la copia viene chiamata <strong>processo figlio<\/strong>. Fork in inglese significa \u00e2\u20ac\u0153<em>forchetta<\/em>\u00e2\u20ac\u009d, il termine non rispecchia altro che il comportamento di questa operazione. Infatti si pu\u00c3\u00b2 associare al manico di una forchetta il processo padre e ad ogni rebbio si pu\u00c3\u00b2 associare un processo figlio.<\/p>\n<p>Bisogna fare attenzione ad usare il forking. Il processo quando genera un figlio, le variabili ed altre risorse <span style=\"text-decoration: underline;\">non vengono condivise<\/span>.<\/p>\n<p>Qui a lato \u00c3\u00a8 mostrato uno schema che riassume sinteticamente il funzionamento di questa tecnica. In un certo punto del programma si effettua una chiamata alla funzione <em>fork<\/em> che divide il programma in due, tale funzione:<\/p>\n<ul>\n<li>se ha esito negativo restituisce<strong> -1<\/strong>, in questo caso non viene generato alcun processo figlio ed <em>errno<\/em> viene settata;<\/li>\n<li>se ha esito positivo restituisce <strong>0 <\/strong>al processo figlio, mentre al processo padre viene restituito il <strong>PID<\/strong> (<em>Process ID<\/em>) del processo figlio.<\/li>\n<\/ul>\n<p>Dato che non \u00c3\u00a8 scopo dell&#8217;articolo illustrare nel dettaglio la tecnica di forking, si rimanda al seguente <a href=\"http:\/\/www.opengroup.org\/pubs\/online\/7908799\/xsh\/fork.html\">link<\/a> [in inglese] per eventuali approfondimenti.<\/p>\n<p><!--more--><\/p>\n<h3>Esempio di forking del processo<\/h3>\n<p>Di seguito \u00c3\u00a8 presente un piccolo codice che metter\u00c3\u00a0 in pratica il concetto di forking. Nel codice c&#8217;\u00c3\u00a8 una variabile che apparentemente sembra essere condivisa.<\/p>\n<pre lang=\"c\">#include &lt; stdio.h &gt;\r\n#include &lt; stdlib.h &gt;\r\n#include &lt; unistd.h &gt;\u00c2\u00a0\u00c2\u00a0 \u00c2\u00a0\/* fork *\/\r\n#include &lt; sys\/types.h &gt;\u00c2\u00a0\u00c2\u00a0 \u00c2\u00a0\/* pid_t *\/\r\nint main(void) {\r\n\tpid_t pid; \/* ID del processo figlio*\/\r\n\tint i;\r\n\r\n\tpid = fork();\r\n\r\n\tif(pid == 0) {\t\/* Processo figlio *\/\r\n\t\tfor(i = 2; i &lt;= 20; i+=2) {\r\n \t\t\tprintf(\"Processo figlio:\\t%d\\n\", i);\r\n \t\t\tsleep(1);\r\n \t\t}\r\n \t} else if(pid &gt; 0) {\t\/* Processo padre *\/\r\n\t\tfor(i = 1; i &lt;= 10; i++) {\r\n\t\t\tprintf(\"Processo padre: %d\\n\", i);\r\n\t\t\tsleep(1);\r\n\t\t}\r\n\t} else {\t\/* Errore *\/\r\n\t\tfprintf(stderr, \"Errore nel fork\\n\");\r\n\t\texit(-1);\r\n\t}\r\n\r\n\treturn 0;\r\n}<\/pre>\n<p>Il codice crea un processo figlio che calcola la tabellina del due, mentre il padre conta fino a 10. I due processi sono eseguiti in parallelo, per capire meglio che sono due processi distinti, nel codice, la variabile <em>i<\/em> \u00c3\u00a8 usata sia dal padre che dal figlio senza entrare in conflitto. Infatti nel momento che si effettua la chiamata <em>fork<\/em> i due processi sono allocati in due zone di memoria diverse, quindi ogni processo avr\u00c3\u00a0 la sua variabile <em>i<\/em>.<\/p>\n<p>Di seguito c&#8217;\u00c3\u00a8 l&#8217;output del programma eseguito sul mio computer.<\/p>\n<pre>alessandro@debian-vm:~\/Desktop$ gcc -std=c89 fork.c -o fork\r\nalessandro@debian-vm:~\/Desktop$ .\/fork\r\nProcesso figlio:        2\r\nProcesso padre: 1\r\nProcesso padre: 2\r\nProcesso figlio:        4\r\nProcesso figlio:        6\r\nProcesso padre: 3\r\nProcesso figlio:        8\r\nProcesso padre: 4\r\nProcesso padre: 5\r\nProcesso figlio:        10\r\nProcesso figlio:        12\r\nProcesso padre: 6\r\nProcesso figlio:        14\r\nProcesso padre: 7\r\nProcesso padre: 8\r\nProcesso figlio:        16\r\nProcesso figlio:        18\r\nProcesso padre: 9\r\nProcesso figlio:        20\r\nProcesso padre: 10\r\nalessandro@debian-vm:~\/Desktop$<\/pre>\n<p>L&#8217;ordine nel quale vengono eseguiti i processi viene stabilito dallo scheduler.<\/p>\n<h2>Server concorrente<\/h2>\n<p>Un <strong>server concorrente<\/strong> \u00c3\u00a8 un server che ha la possibilit\u00c3\u00a0 di accettare pi\u00c3\u00b9 connessioni contemporanee da parte dei client. La base del funzionamento \u00c3\u00a8 la stessa del server sequenziale (per approfondimenti si veda l&#8217;articolo <a href=\"http:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux\">precedente<\/a>), ma con una lieve modifica:<\/p>\n<ol>\n<li>Creare una socket<\/li>\n<li>Effettuare il binding della socket<\/li>\n<li>Mettere in ascolto la socket<\/li>\n<li>Accettare la connessione da parte del client<\/li>\n<li><em><strong>Copia del processo tramite fork()<\/strong><\/em><\/li>\n<li>Effettuare la comunicazione tramite le funzioni recv() e send<\/li>\n<\/ol>\n<p>Il passo scritto in neretto \u00c3\u00a8 quello che si andr\u00c3\u00a0 ad analizzare pi\u00c3\u00b9 avanti in questo articolo. Il server concorrente appena accetta una connessione da parte del client si sdoppia.<\/p>\n<h2>Il codice<\/h2>\n<p>Il codice cambia rispetto a quello dell&#8217;articolo precedente in due parti:<\/p>\n<ol>\n<li>Il server \u00c3\u00a8 ovviamente gestito diversamente perch\u00c3\u00a9 genera i processi figlio.<\/li>\n<li>Ogni client pu\u00c3\u00b2 dialogare con il server inviando pi\u00c3\u00b9 messaggi. Per disconnettere il client dal server \u00c3\u00a8 possibile farlo inviando la stringa <em>EXIT<\/em>.<\/li>\n<\/ol>\n<p>Se si vuole mettere il server in ascolto per pi\u00c3\u00b9 client, si deve creare quindi un loop. Si pu\u00c3\u00b2 fare in questo modo:<\/p>\n<pre lang=\"c\">while(1) {\r\n\tsd_client = accept(sd_server, (struct sockaddr *)&amp;client_addr, &amp;address_size);\r\n\tif(sd_client &lt; 0) {\r\n\t\tprintf(\"Errore nella chiamata accept\\n\");\r\n\t\texit(-1);\r\n\t}\r\n}<\/pre>\n<p>Ora c&#8217;\u00c3\u00a8 bisogno di dividere il processo principale, ogni processo figlio gestir\u00c3\u00a0 la comunicazione con il rispettivo client:<\/p>\n<pre lang=\"c\">pid = fork();\r\n\r\nif(pid == 0) { \/* figlio *\/\r\n} else if(pid &gt; 0) { \/* padre *\/\r\n\tclose(sd_client);\r\n} else {\r\n\tprintf(\"Errore nella creazione del figlio\\n\");\r\n\texit(-1);\r\n}<\/pre>\n<p>Il server accetta la chiamata da parte del client e si divide. Al processo padre ora non serve pi\u00c3\u00b9 la socket del client, perch\u00c3\u00a9 verr\u00c3\u00a0 gestita dal processo figlio. Non pu\u00c3\u00b2 mancare anche la visualizzazione di un messaggio di errore se fallisce il forking del processo. Il codice a questo punto \u00c3\u00a8 il seguente:<\/p>\n<pre lang=\"c\">while(1) {\r\n\tsd_client = accept(sd_server, (struct sockaddr *)&amp;client_addr, &amp;address_size);\r\n\tif(sd_client &lt; 0) { \t\t \t\tprintf(\"Errore nella chiamata accept\\n\");  \t\texit(-1);  \t}  \tpid = fork();  \tif(pid == 0) { \/* figlio *\/  \t} else if(pid &gt; 0) { \/* padre *\/\r\n\t\tclose(sd_client);\r\n\t} else {\r\n\t\tprintf(\"Errore nella creazione del figlio\\n\");\r\n\t\texit(-1);\r\n\t}\r\n}<\/pre>\n<p>Si passa ora alla gestione del client, all&#8217;interno del blocco <em>if<\/em> si inseriscono le seguenti righe:<\/p>\n<pre lang=\"c\">if(pid == 0) { \/* figlio *\/\r\n\tclose(sd_server);\r\n\trecv(sd_client, buff, sizeof(buff), 0);\r\n\tprintf(\"Dati ricevuti: %s\", buff);\r\n\tstrcpy(buff, \"Tutto OK!\\n\");\r\n\tsend(sd_client, buff, strlen(buff), 0);\r\n\tclose(sd_client);\r\n\texit(0);\r\n}<\/pre>\n<p>La socket del server \u00c3\u00a8 possibile chiuderla anche dopo (si ricorda che non \u00c3\u00a8 la stessa socket del processo padre, ma semplicemente una copia). Effettuate le operazioni di ricezione ed invio si chiude la socket del client ed il <span style=\"text-decoration: underline;\">processo figlio<\/span>, utilizzando <em>exit(0)<\/em>.<\/p>\n<p>Il server \u00c3\u00a8 finito, per completarlo si potrebbe rendere ciclico il dialogo con il client:<\/p>\n<pre lang=\"c\">if(pid == 0) { \/* figlio *\/\r\n\tclose(sd_server);\r\n\r\n\twhile(1) {\r\n\t\tmemset(buff, '\\0', MAX);\t\/* si cancellano i dati ricevuti in precedenza *\/\r\n\t\trecv(sd_client, buff, sizeof(buff), 0);\r\n\t\tprintf(\"Dati ricevuti: %s\", buff);\r\n\t\tstrcpy(buff, \"Tutto OK!\\n\");\r\n\t\tsend(sd_client, buff, strlen(buff), 0);\r\n\t}\t\t\t\r\n\r\n\tclose(sd_client); \/* disconnessione *\/\r\n\texit(0); \/* chiude il processo *\/\r\n}<\/pre>\n<p>Bene, si hanno un client ed un server che interagiscono ciclicamente, l&#8217;unico problema \u00c3\u00a8 che andranno avanti fino all&#8217;infinito finch\u00c3\u00a9 non cade la connessione o arrestando forzatamente uno dei due processi. Per rimediare a questo, basta inserire un controllo nel <em>while<\/em>:<\/p>\n<pre lang=\"c\">if(pid == 0) { \/* figlio *\/\r\n\tclose(sd_server);\r\n\tchar tmp_string[MAX]; \/* servir\u00c3\u00a0 per capire se chiudere o meno la connessione con il client *\/\r\n\r\n\twhile(strcmp(tmp_string, \"EXIT\\r\\n\") != 0) { \/* se si riceve il comando EXIT, termina il ciclo *\/\r\n\t\tmemset(buff, '\\0', MAX);\t\/* si cancellano i dati ricevuti in precedenza *\/\r\n\t\tmemset(tmp_string, '\\0', MAX);\r\n\t\trecv(sd_client, buff, sizeof(buff), 0);\r\n\t\tstrcpy(tmp_string, buff);\r\n\t\tprintf(\"Dati ricevuti: %s\", buff);\r\n\t\tstrcpy(buff, \"Tutto OK!\\n\");\r\n\t\tsend(sd_client, buff, strlen(buff), 0);\r\n\t}\r\n\r\n\tclose(sd_client); \/* disconnessione *\/\r\n\texit(0); \/* chiude il processo *\/\r\n}<\/pre>\n<p>Quando al server arriva la stringa <em>EXIT<\/em>, il client viene disconnesso ed il server si mette in ascolto per un&#8217;altra connessione. Avrete notato che manca il codice del client, infatti per collegarsi al server basta eseguire da terminale il seguente comando:<\/p>\n<pre>telnet 127.0.0.1 1745<\/pre>\n<p>Provate ad aprire pi\u00c3\u00b9 connessioni con telnet e vedere come le gestisce il server. Questo \u00c3\u00a8 tutto, alla prossima!<\/p>\n<p><a href=\"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/socket_fork.zip\">Scarica il codice completo<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nel primo articolo abbiamo analizzato il funzionamento delle socket e di un server con rispettivo client. In questo vedremo un modo di programmare un tipico server concorrente utilizzando la funzione fork(). Prima di addentrarci nel codice del server concorrente, vediamo un po&#8217; come funziona la tecnica di forking. Forking Il forking consente di effettuare delle [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Come programmare le socket in ambienti GNU\/Linux (Parte 2) - OScene.net<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Come programmare le socket in ambienti GNU\/Linux (Parte 2) - OScene.net\" \/>\n<meta property=\"og:description\" content=\"Nel primo articolo abbiamo analizzato il funzionamento delle socket e di un server con rispettivo client. In questo vedremo un modo di programmare un tipico server concorrente utilizzando la funzione fork(). Prima di addentrarci nel codice del server concorrente, vediamo un po&#8217; come funziona la tecnica di forking. Forking Il forking consente di effettuare delle [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2\" \/>\n<meta property=\"og:site_name\" content=\"OScene.net\" \/>\n<meta property=\"article:published_time\" content=\"2010-10-20T11:00:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2010-10-20T11:07:34+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma-157x300.png\" \/>\n<meta name=\"author\" content=\"Alessandro Iezzi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alessandro Iezzi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2\",\"url\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2\",\"name\":\"Come programmare le socket in ambienti GNU\/Linux (Parte 2) - OScene.net\",\"isPartOf\":{\"@id\":\"https:\/\/www.oscene.net\/it\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#primaryimage\"},\"thumbnailUrl\":\"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma-157x300.png\",\"datePublished\":\"2010-10-20T11:00:50+00:00\",\"dateModified\":\"2010-10-20T11:07:34+00:00\",\"author\":{\"@id\":\"https:\/\/www.oscene.net\/it\/#\/schema\/person\/fcc8bb436ed9b2f965fbf1f271db0e52\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#primaryimage\",\"url\":\"https:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma.png\",\"contentUrl\":\"https:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma.png\",\"width\":\"477\",\"height\":\"910\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.oscene.net\/it\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Come programmare le socket in ambienti GNU\/Linux (Parte 2)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.oscene.net\/it\/#website\",\"url\":\"https:\/\/www.oscene.net\/it\/\",\"name\":\"OScene.net\",\"description\":\"Ope(rating)n S(ystem)ource Scenario\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.oscene.net\/it\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.oscene.net\/it\/#\/schema\/person\/fcc8bb436ed9b2f965fbf1f271db0e52\",\"name\":\"Alessandro Iezzi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/www.oscene.net\/it\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7befe097eb2c9851e9b096e4d5383f7f?s=96&d=retro&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/7befe097eb2c9851e9b096e4d5383f7f?s=96&d=retro&r=g\",\"caption\":\"Alessandro Iezzi\"},\"sameAs\":[\"http:\/\/iezziweb.webhop.org\"],\"url\":\"https:\/\/www.oscene.net\/it\/author\/gray_fox\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Come programmare le socket in ambienti GNU\/Linux (Parte 2) - OScene.net","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2","og_locale":"it_IT","og_type":"article","og_title":"Come programmare le socket in ambienti GNU\/Linux (Parte 2) - OScene.net","og_description":"Nel primo articolo abbiamo analizzato il funzionamento delle socket e di un server con rispettivo client. In questo vedremo un modo di programmare un tipico server concorrente utilizzando la funzione fork(). Prima di addentrarci nel codice del server concorrente, vediamo un po&#8217; come funziona la tecnica di forking. Forking Il forking consente di effettuare delle [&hellip;]","og_url":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2","og_site_name":"OScene.net","article_published_time":"2010-10-20T11:00:50+00:00","article_modified_time":"2010-10-20T11:07:34+00:00","og_image":[{"url":"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma-157x300.png"}],"author":"Alessandro Iezzi","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Alessandro Iezzi","Tempo di lettura stimato":"6 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2","url":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2","name":"Come programmare le socket in ambienti GNU\/Linux (Parte 2) - OScene.net","isPartOf":{"@id":"https:\/\/www.oscene.net\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#primaryimage"},"image":{"@id":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#primaryimage"},"thumbnailUrl":"http:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma-157x300.png","datePublished":"2010-10-20T11:00:50+00:00","dateModified":"2010-10-20T11:07:34+00:00","author":{"@id":"https:\/\/www.oscene.net\/it\/#\/schema\/person\/fcc8bb436ed9b2f965fbf1f271db0e52"},"breadcrumb":{"@id":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#primaryimage","url":"https:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma.png","contentUrl":"https:\/\/www.oscene.net\/it\/wp-content\/uploads\/2010\/09\/diagramma.png","width":"477","height":"910"},{"@type":"BreadcrumbList","@id":"https:\/\/www.oscene.net\/it\/programmazione\/c\/come-programmare-le-socket-in-ambienti-gnulinux-parte-2#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.oscene.net\/it"},{"@type":"ListItem","position":2,"name":"Come programmare le socket in ambienti GNU\/Linux (Parte 2)"}]},{"@type":"WebSite","@id":"https:\/\/www.oscene.net\/it\/#website","url":"https:\/\/www.oscene.net\/it\/","name":"OScene.net","description":"Ope(rating)n S(ystem)ource Scenario","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.oscene.net\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/www.oscene.net\/it\/#\/schema\/person\/fcc8bb436ed9b2f965fbf1f271db0e52","name":"Alessandro Iezzi","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/www.oscene.net\/it\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/7befe097eb2c9851e9b096e4d5383f7f?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7befe097eb2c9851e9b096e4d5383f7f?s=96&d=retro&r=g","caption":"Alessandro Iezzi"},"sameAs":["http:\/\/iezziweb.webhop.org"],"url":"https:\/\/www.oscene.net\/it\/author\/gray_fox"}]}},"_links":{"self":[{"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/posts\/392"}],"collection":[{"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/comments?post=392"}],"version-history":[{"count":120,"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/posts\/392\/revisions"}],"predecessor-version":[{"id":567,"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/posts\/392\/revisions\/567"}],"wp:attachment":[{"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/media?parent=392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/categories?post=392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.oscene.net\/it\/wp-json\/wp\/v2\/tags?post=392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}