Strumenti Utente

Strumenti Sito


programmazione:d:tcp_socket

Socket in linguaggio D

Autore: Fabio Di Matteo
Ultima revisione: 24/07/2025 11:53

Alcuni esempi base.

TCP server (Hello world)

import std.stdio;
import std.socket;
import std.string;
 
int router(Socket c, string m)
{
    c.send("Il server risponde (echo): " ~ m);
    m=m.strip();
    m=m.replace("\n", "");
    writeln("Il client invia:'",m,"'");
 
    if (m=="bye")
    {
        writeln("Client chide disconnessione.");
        c.send("Disconnesso dal server.");
        return 1;
    }
 
 
   return 0;
}
 
 
void main() {
    auto serverSocket = new TcpSocket();
    auto address = new InternetAddress("127.0.0.1", 3131);
    serverSocket.bind(address);
    serverSocket.listen(5);
    writeln("Server in ascolto su 127.0.0.1:3131...");
 
    while (true) //server in ascolto 
    {
        auto clientSocket = serverSocket.accept();
        writeln("Connessione accettata da ", clientSocket.remoteAddress);
 
        ubyte[] buffer = new ubyte[1024];
        size_t bytesRead;
 
        while(true)//inizio la discussione con un client
        {
            bytesRead = clientSocket.receive(buffer[]);
            string message = cast(string) buffer[0 .. bytesRead];
            int r = router(clientSocket,message);
            if (r==1) 
            {
                clientSocket.close();
                break;
            }
        }
 
        clientSocket.close();
    }
 
    serverSocket.close();
}

Base per un esempio piu' completo

In questo esempio il client comunicherà attraverso l'invio di un pacchetto dati json. Verrà creta una struttura dati a tabella in ram dove questi messaggi verranno conservati. L'idea è che piu' client possano comunicare attraverso questa tabella. L'esempio non è ancora completo, ma dà l'idea di fondo .

“A partire dalla versione 2.030 di dmd, la classe di archiviazione predefinita per le variabili statiche e globali sarà la memoria locale per thread (TLS), anziché il classico segmento di dati globali. Anche se la maggior parte del codice D dovrebbe compilare e funzionare correttamente senza modifiche, potrebbero sorgere alcuni problemi.” Dunque per condividere una variabile globale ra diversi thread marcarla come shared - Migrating to Shared
import std.stdio;
import std.socket;
import std.string;
 
import std.json;
import std.conv;
import std.datetime;
 
import std.concurrency; 
import core.thread; 
import core.thread.osthread;
import core.sync.mutex;
 
/* An package example
 *  {"action":"action_name","user":"user_name","password":"password","to":"user_destination","var":"var_name","payload":"message body"}
 */
 
Mutex mtx ;
 
shared struct payloadTableRecord
{
    string user,password,to,payload, action;
    InternetAddress addr;
    long timestamp;
}
 
shared payloadTableRecord[] payloadTable;
 
@system void handleAction(Socket c, payloadTableRecord t)
{
    if (t.action=="ping")
    {
       c.send("pong per utente "~t.user);
    }
 
    if (t.action=="bye")
    {
        writeln(t.user," close connection.");
        c.send(t.user~" close connection.");
        c.close();
    }
 
 
    if (t.action=="get")
    {
       try{
            foreach (record; payloadTable) 
            {
                writeln(record.user," ",record.to);
                if (record.to == t.user) {
                    c.send("Message from " ~ record.user ~ ": " ~ record.payload);
                    //break;
                }
            }
       }catch(Exception e){
            writeln("Error: ",e.msg);
            c.send("");
       } finally{
       }
    }
}
 
@system void updatePayloadtable(Socket c)
{
    ubyte[] buffer = new ubyte[1024];
    size_t bytesRead;
    string m;
    JSONValue j;
    shared payloadTableRecord t;
 
    while(c !is null) 
    {    
        try{
            bytesRead = c.receive(buffer[]);
            m = cast(string) buffer[0 .. bytesRead];
            if (bytesRead == 0)
            { 
                c.close();
                writeln("Nessuna risposta dal client. Connesione chiusa.");
                break;
            }     
            j = parseJSON(m);
 
            t.user=j["user"].str;
            t.password=j["password"].str;
            t.to=j["to"].str;
            t.payload=j["payload"].str;
            t.timestamp=Clock.currTime().toUnixTime();
            t.action=j["action"].str;
 
            payloadTable ~= t;
            //writeln(payloadTable);        
            handleAction(c,t);
 
        }catch (Exception e){
            writeln("Error: ",e.msg);
            Thread.sleep( dur!("msecs")( 500 ) );
        } 
 
    }//while
} 
 
 
 
int main() {
    mtx = new Mutex();
    auto serverSocket = new TcpSocket();
    auto address = new InternetAddress("0.0.0.0", 3131);
    serverSocket.bind(address);
    serverSocket.listen(1);
    writeln("Server in ascolto su 127.0.0.1:3131...");
 
    while (true)  
    {
 
        auto client = serverSocket.accept();
        writeln("Connessione accettata da ",  client.remoteAddress);
 
         auto t = new Thread(() {
            updatePayloadtable(client);
        });
        t.start();
    }
}
programmazione/d/tcp_socket.txt · Ultima modifica: 27/07/2025 09:54 da Fabio Di Matteo