Homepage  Il progetto dsy.it è l'unofficial support site dei corsi di laurea del Dipartimento di Scienze dell'Informazione e del Dipartimento di Informatica e Comunicazione della Statale di Milano. E' un servizio degli studenti per gli studenti, curato in modo no-profit da un gruppo di essi. I nostri servizi comprendono aree di discussione per ogni Corso di Laurea, un'area download per lo scambio file, una raccolta di link e un motore di ricerca, il supporto agli studenti lavoratori, il forum hosting per Professori e studenti, i blog, e molto altro...
In questa sezione è indicizzato in textonly il contenuto del nostro forum


.dsy:it. .dsy:it. Archive > Didattica > Corsi N - Z > Reti di calcolatori
 
[LAB] Programmazione di rete in C
Clicca QUI per vedere il messaggio nel forum
futurbaggio
Originally posted by yeah
qualcuno può postare delcodice che funziona in linux, che faccio una prova? Grazie :cool:


Client.c
code:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> main(){ int sd, server_sd; struct sockaddr_in client; struct hostent *hp; int address_size; int port = 3000; char buff_in[8000]; char buff_out[8000]; hp = gethostbyname("127.0.0.1"); // Creazione di una nuova socket TCP sd = socket(AF_INET,SOCK_STREAM,0); // Definizione delle caratteristiche della socket bzero(&client, sizeof(client)); client.sin_family = PF_INET; client.sin_port = htons(port); client.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; server_sd = connect(sd, (struct sockaddr*)&client, sizeof(client)); // Prende da tastiera il messaggio da inviare al server printf("Io: "); scanf("%s", buff_in); send (sd, buff_in, strlen(buff_in), 0); // Stampa a video i dati ricevuti dal server recv(sd, buff_out, sizeof(buff_out), 0); printf("Lui: %s \n", buff_out); // Chiusura socket close(sd); return EXIT_SUCCESS; }



Server.c
code:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> main(){ int sd, bind_sd, client_sd; struct sockaddr_in client; struct sockaddr_in server; int address_size; int port = 3000; char buff_in[8000]; char buff_out[8000]; // Creazione di una nuova socket TCP sd = socket(AF_INET,SOCK_STREAM,0); // Definizione delle caratteristiche della Server socket server.sin_family = PF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = INADDR_ANY; // Associazione della socket ad un processo bind_sd = bind(sd,(struct sockaddr *)&server, sizeof(server)); while(1){ // Attivazione della socket listen(sd,20); // Server socket in attesa di richieste del client client_sd = accept(sd, (struct sockaddr *)&client, &address_size); // Stampa a video i dati ricevuti dal client recv(client_sd, buff_in, sizeof(buff_in), 0); printf("Lui: %s \n", buff_in); // Prende da tastiera il messaggio da inviare all'altro interlocutore printf("Io: "); scanf("%s", buff_out); send (client_sd, buff_out, strlen(buff_out), 0); // Chiusura socket close(client_sd); } return EXIT_SUCCESS; }


Roberto

yeah
Ottimo :)
Ora salvo e vedo cosa si può fare :cool:

GinoPilotino
bravissimissimo :D

yeah
Client.c
code:
#include <stdio.h> #include <stdlib.h> /* #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> */ #include <winsock2.h> int main() { /* Variabile per l'uso delle socket di Windows */ WSADATA wsaData; int sd, server_sd; struct sockaddr_in client; struct hostent *hp; int address_size; int port = 3000; char buff_in[8000]; char buff_out[8000]; /* Inizializzazione l'uso di ws2_32.dll da parte del processo */ WSAStartup(MAKEWORD( 2, 2 ), &wsaData); hp = gethostbyname("127.0.0.1"); // Creazione di una nuova socket TCP sd = socket(AF_INET,SOCK_STREAM,0); // Definizione delle caratteristiche della socket /* bzero(&client, sizeof(client)); */ memset(&client, 0, sizeof(client)); client.sin_family = PF_INET; client.sin_port = htons(port); client.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; server_sd = connect(sd, (struct sockaddr*)&client, sizeof(client)); // Prende da tastiera il messaggio da inviare al server printf("Io: "); scanf("%s", buff_in); send (sd, buff_in, strlen(buff_in), 0); // Stampa a video i dati ricevuti dal server recv(sd, buff_out, sizeof(buff_out), 0); printf("Lui: %s \n", buff_out); // Chiusura socket closesocket(sd); /*close(sd);*/ /* Termina l'uso di ws2_32.dll */ WSACleanup(); return EXIT_SUCCESS; }


Server.c
code:
#include <stdio.h> #include <stdlib.h> /* #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> */ #include <winsock2.h> int main() { /* Variabile per l'uso delle socket di Windows */ WSADATA wsaData; int sd, bind_sd, client_sd; struct sockaddr_in client; struct sockaddr_in server; int address_size; int port = 3000; char buff_in[8000]; char buff_out[8000]; /* Inizializzazione l'uso di ws2_32.dll da parte del processo */ WSAStartup(MAKEWORD( 2, 2 ), &wsaData); // Creazione di una nuova socket TCP sd = socket(AF_INET,SOCK_STREAM,0); // Definizione delle caratteristiche della Server socket server.sin_family = PF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = INADDR_ANY; // Associazione della socket ad un processo bind_sd = bind(sd,(struct sockaddr *)&server, sizeof(server)); while(1) { // Attivazione della socket listen(sd,20); // Server socket in attesa di richieste del client client_sd = accept(sd, (struct sockaddr *)&client, &address_size); // Stampa a video i dati ricevuti dal client recv(client_sd, buff_in, sizeof(buff_in), 0); printf("Lui: %s \n", buff_in); // Prende da tastiera il messaggio da inviare all'altro interlocutore printf("Io: "); scanf("%s", buff_out); send(client_sd, buff_out, strlen(buff_out), 0); // Chiusura socket closesocket(client_sd); /* close(client_sd); */ } /* Termina l'uso di ws2_32.dll */ WSACleanup(); return EXIT_SUCCESS; }


I miei commenti sono tra /* e */, gli altri sono di futurbaggio.

In pratica ho sostituito i file header con
code:
#include <winsock2.h>

Ho aggiunto la variabile
code:
WSAData wsadata
che server per l'inizializzazione della dll, ho chiamato WSAStartup() prima di ogni funzione di rete e WSACleanup() alla fine delle funzioni di rete.

Poi ho sostituito
code:
bzero(&client, sizeof(client)); close(sd);

con
code:
memset(&client, 0, sizeof(client)); closesocket(sd);


Avrei dovuto dichiarare le variabili quali server_sd come di tipo SOCKET, ma alla fine si tratta sempre di numeri interi (con la differenza che i secondi sono senza segno).

[edit]

Per compilare dovete aggiungere la libreria ws2_32 (es con GCC -lws2_32)

Flavia
Mi sento troppo ignorante!

Non è che potete svolgere qualche tema d'esame e poi postarlo??? :please:
:lode:

m@cCo
A cosa serve la dll?

Ciao

GinoPilotino
credo che il messaggio di yeah si riferisca alle winsocket, ossia alle socket in c sotto windows.
ovviamente non ne sono sicuro al 100% perchè il c non l'ho mai visto.

m@cCo
Ah boh io sto usando cygwin.
Non ho capito questa linea di codice:

code:
client.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr;

perchè non usare inet_address() o inet_aton()?

Le frecce servono ad accedere ai campi di una classe no?
Qualcuno sarebbe così gentile da spiegarmi cosa fa quella riga di codice?

Ciao

futurbaggio
Originally posted by m@cCo
Le frecce servono ad accedere ai campi di una classe no?
Qualcuno sarebbe così gentile da spiegarmi cosa fa quella riga di codice?


In C non esiste il concetto di classe ma qualcosa che gli assomiglia, le strutture, che sono un tipo di dato complesso composto da + tipi primitivi (int, double, char, etc) e/o da altre strutture.
In particolare noi utilizziamo la struttura socketaddr_in che è composta da vari attributi semplici (sinf_family o sin_port) e da una sotto-struttura (sin_addr), questa a sua volta contiene l'attributo s_addr.
Nella riga che hai indicato in pratica si copia in questo attributo il valore dell'attributo s_addr di un'altra struttura analoga che è stata creata poco sopra:

hp = gethostbyname("127.0.0.1");

C'è una differenza sostanziale però tra la struttura 'client' (ai cui attributi accediamo attraverso l'operatore '.') e la struttura 'hp', infatti 'hp' è definito come un puntatore per questo utilizziamo l'opertore '->' per scorrere gli attributi.
Questa parte del codice (struct in_addr*) non è altro che un'operazione di cast, spero di essermi spiegato, mi rendo conto che non è una cosa semplicissima anche perchè i puntatori non esistono in Java.

Roberto

yeah
Il commento riguardante la dll arriva direttamente dall'help di Microsoft :D

Sì, il mio codice lavora con le socket di Windows.

In Windows le funzioni di sistema sono tutte organizzate in dll, librerie che possono essere caricate da vari programmi.

In sostanza, ci sono un tot di funzioni comuni a più programmi. Invece di 'inserire' il codice di quelle funzioni in ogni programma, quel codice è raccolto un una dll, che i programmi possono caricare, risparmiando spazio.

La stessa funzionalità (credo con un principio simile) esiste anche in Unix/Linux.

m@cCo
Originally posted by futurbaggio
In C non esiste il concetto di classe ma qualcosa che gli assomiglia, le strutture, che sono un tipo di dato complesso composto da + tipi primitivi (int, double, char, etc) e/o da altre strutture.
In particolare noi utilizziamo la struttura socketaddr_in che è composta da vari attributi semplici (sinf_family o sin_port) e da una sotto-struttura (sin_addr), questa a sua volta contiene l'attributo s_addr.
Nella riga che hai indicato in pratica si copia in questo attributo il valore dell'attributo s_addr di un'altra struttura analoga che è stata creata poco sopra:

hp = gethostbyname("127.0.0.1");

C'è una differenza sostanziale però tra la struttura 'client' (ai cui attributi accediamo attraverso l'operatore '.') e la struttura 'hp', infatti 'hp' è definito come un puntatore per questo utilizziamo l'opertore '->' per scorrere gli attributi.
Questa parte del codice (struct in_addr*) non è altro che un'operazione di cast, spero di essermi spiegato, mi rendo conto che non è una cosa semplicissima anche perchè i puntatori non esistono in Java.

Roberto


Si conosco i puntatori in c, semplicemente non capisco perchè tu abbia utilizzato la funzione gethostbyname() invece di utilizzare le più semplici inet_address() o inet_aton() che traducono l'indirizzo espresso in notazione decimale in un long a 32 bit.

Altra cosa:

ho provato a far girare i tuoi client e server ma non funzionano, o meglio, il server non visualizza ciò che scrivo sul client passando subito al proprio input, mentre il client non visualizza l'input del server.

Ciao

futurbaggio
Originally posted by m@cCo
Si conosco i puntatori in c, semplicemente non capisco perchè tu abbia utilizzato la funzione gethostbyname() invece di utilizzare le più semplici inet_address() o inet_aton() che traducono l'indirizzo espresso in notazione decimale in un long a 32 bit.


Credo che ognuno sia libero di usare quello che più crede facile e semplice, io mi sono rifatto agli esempi di cassiano e mi sono studiato quelle primitive.

Originally posted by m@cCo
Altra cosa:
ho provato a far girare i tuoi client e server ma non funzionano, o meglio, il server non visualizza ciò che scrivo sul client passando subito al proprio input, mentre il client non visualizza l'input del server.


Con gcc 3.3.4 su Debian stable funziona...

Roberto

m@cCo
Allora sarà colpa di windows come al solito, vabè...grazie della spiegazione.
Credete che il prof terrà conto dell'utilizzo o meno delle primitive usate negli esempi?
O come dice futurbaggio ognuno è libero di usare ciò che vuole, perchè non mi pare che su java le cose stiano proprio così...

Ciao

futurbaggio
Originally posted by m@cCo
Allora sarà colpa di windows come al solito, vabè...grazie della spiegazione.


Forse per Windows dovresti usare il codice di yeah, io non ti posso aiutare perchè non ho windows...

Roberto

m@cCo
No io sto usando un emulatore di ambiente unix sotto windows (cygwin), però se tu mi dici che sotto linux il codice da te postato funziona correttamente l'unica cosa che mi viene in mente è che a dare problemi sia la gestione della rete di windows, quando ho tempo proverò con linux.

Ciao

GinoPilotino
roberto a quando il codice funzionante tramite UDP?
o salvatore, illumina il mio cammino :D

futurbaggio
Ecco i codici di una comunicazione UDP client-server in C.

Client.c
code:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> main(){ int sd, rc, i; struct sockaddr_in clientAddress, serverAddress; struct hostent *hp; char buff_in[8000]; hp = gethostbyname("127.0.0.1"); serverAddress.sin_family = PF_INET; serverAddress.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; serverAddress.sin_port = htons(5001); sd = socket(AF_INET,SOCK_DGRAM,0); clientAddress.sin_family = PF_INET; clientAddress.sin_addr.s_addr = INADDR_ANY; clientAddress.sin_port = htons(0); rc = bind(sd, (struct sockaddr *) &clientAddress, sizeof(clientAddress)); printf("Messaggio da inviare al server UDP: "); scanf("%s", buff_in); rc = sendto(sd, buff_in, strlen(buff_in), 0, (struct sockaddr *)&serverAddress, sizeof(serverAddress)); close(sd); return EXIT_SUCCESS; }


Server.c
code:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> main(){ int sd, rc, n, clientLength; struct sockaddr_in clientAddress, serverAddress; char buff_in[8000]; sd=socket(AF_INET, SOCK_DGRAM, 0); serverAddress.sin_family = PF_INET; serverAddress.sin_addr.s_addr = INADDR_ANY; serverAddress.sin_port = htons(5001); rc = bind (sd, (struct sockaddr *) &serverAddress,sizeof(serverAddress)); while(1) { clientLength = sizeof(clientAddress); n = recvfrom(sd, buff_in, sizeof(buff_in), 0, (struct sockaddr *) &clientAddress, &clientLength); printf("Ricevuto da %s:%d: %s \n",inet_ntoa(clientAddress.sin_addr.s_addr),ntohs(clientAddress.sin_port), buff_in); } return EXIT_SUCCESS; }


Roberto

Powered by: vbHome (lite) v4.1 and vBulletin v2.3.1 - Copyright ©2000 - 2002, Jelsoft Enterprises Limited
Mantained by dsy crew (email) | Collabora con noi | Segnalaci un bug | Archive | Regolamento |Licenze | Thanks | Syndacate