Salve.
Ho due semplici programmi udpclient e udpserver che utilizzano i socket udp; il server fa echo al client dei dati che arrivano. Ad ogni iterazione ambo i programmi stampano ip e numero di porta contenuti nelle strutture sockaddr_in che passano alle sendto() e ricevono dalle recvfrom().
Vi posto qui i programmi:
udpclient.c
codice:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define BUFFSIZE 255
void Die(char *mess) { perror(mess); exit(1); }
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in echoserver;
struct sockaddr_in echoclient;
char buffer[BUFFSIZE];
unsigned int echolen, clientlen;
int received = 0;
if (argc != 4)
{
fprintf(stderr, "USAGE: %s <server_ip> <word> <port>\n", argv[0]);
exit(1);
}
/* Create the UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
Die("Failed to create socket");
/* Construct the server sockaddr_in structure */
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = inet_addr(argv[1]); /* IP address */
echoserver.sin_port = htons(atoi(argv[3])); /* server port */
/* Send the word to the server */
echolen = strlen(argv[2]);
while(1)
{
if (sendto(sock, argv[2], echolen, 0, (struct sockaddr *) &echoserver, sizeof(echoserver)) != echolen)
Die("Mismatch in number of sent bytes");
/* Receive the word back from the server */
fprintf(stdout, "Received: ");
clientlen = sizeof(echoclient);
if ((received = recvfrom(sock, buffer, BUFFSIZE, 0, (struct sockaddr *) &echoclient, &clientlen)) != echolen)
Die("Mismatch in number of received bytes");
/* Check that client and server are using same socket */
if (echoserver.sin_addr.s_addr != echoclient.sin_addr.s_addr)
Die("Received a packet from an unexpected server");
buffer[received] = '\0'; /* Assure null terminated string */
fprintf(stdout, buffer);
fprintf(stdout, "\n");
printf("%s:%i %s:%i\n",inet_ntoa(echoserver.sin_addr),ntohs(echoserver.sin_port),inet_ntoa(echoclient.sin_addr),ntohs(echoclient.sin_port));
sleep(1);
}
close(sock);
exit(0);
}
udpserver.c
codice:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define BUFFSIZE 255
void Die(char *mess) { perror(mess); exit(1); }
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in echoserver;
struct sockaddr_in echoclient;
char buffer[BUFFSIZE];
unsigned int echolen, clientlen, serverlen;
int received = 0;
if (argc != 2)
{
fprintf(stderr, "USAGE: %s <port>\n", argv[0]);
exit(1);
}
/* Create the UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
Die("Failed to create socket");
/* Construct the server sockaddr_in structure */
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* Any IP address */
echoserver.sin_port = htons(atoi(argv[1])); /* server port */
/* Bind the socket */
serverlen = sizeof(echoserver);
if (bind(sock, (struct sockaddr *) &echoserver, serverlen) < 0)
Die("Failed to bind server socket");
/* Run until cancelled */
while (1)
{
/* Receive a message from the client */
clientlen = sizeof(echoclient);
if ((received = recvfrom(sock, buffer, BUFFSIZE, 0, (struct sockaddr *) &echoclient,&clientlen)) < 0)
Die("Failed to receive message");
fprintf(stderr, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
/* Send the message back to client */
if (sendto(sock, buffer, received, 0,(struct sockaddr *) &echoclient, sizeof(echoclient)) != received)
Die("Mismatch in number of echo'd bytes");
printf("%s:%i %s:%i\n",inet_ntoa(echoserver.sin_addr),ntohs(echoserver.sin_port),inet_ntoa(echoclient.sin_addr),ntohs(echoclient.sin_port));
}
return 0;
}
Eseguo i due programmi sulla stessa macchina, ma su due diverse shell:
codice:
[root@localhost socket]# ./udpserver 7000
Client connected: 192.168.211.156
0.0.0.0:7000 0.0.0.0:46166
Client connected: 192.168.211.156
0.0.0.0:7000 0.0.0.0:46166
Client connected: 192.168.211.156
0.0.0.0:7000 0.0.0.0:46166
Client connected: 192.168.211.156
0.0.0.0:7000 0.0.0.0:46166
Client connected: 192.168.211.156
0.0.0.0:7000 0.0.0.0:46166
codice:
[root@localhost socket]# ./udpclient 192.168.211.156 "prova" 7000
Received: prova
192.168.211.156:7000 192.168.211.156:7000
Received: prova
192.168.211.156:7000 192.168.211.156:7000
Received: prova
192.168.211.156:7000 192.168.211.156:7000
Received: prova
192.168.211.156:7000 192.168.211.156:7000
Received: prova
192.168.211.156:7000 192.168.211.156:7000
Tuttavia, non capisco il perché, il client riceve mediante la recvfrom() la struttura echoclient di tipo sockaddr_in e ne riesce a stampare echoclient.sin_addr, mentre il server mediante la recvfrom() riceve echoclient e stampa echoclient.sin_addr dà in output 0.0.0.0. Eppure, la struttura echoclient deve contenere da qualche parte l'indirizzo ip del mittente, infatti passando tale struttura alla sendto() il server riesce ad inviare correttamente il messaggio di risposta al client. Qualcuno sa dirmi il perché? E' forse dovuto al fatto che eseguo i programmi sulla stessa macchina e quindi, l'indirizzo IP è uguale?
Grazie.