 | |
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 |
[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 variabilecode: 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 |
|
|
|
|