Client code
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
int main ()
{
struct sockaddr_in server ;
struct socklen_t;
int sockid,status,count,count1 ;
char buffer[1024];
char buffer1[1024];
/* socket */
sockid = socket( AF_INET, SOCK_STREAM,0);
if (sockid == -1)
{
printf("could not create socket");
}
else
{
printf(" socket created\n");
}
memset((char *) &server, 0, sizeof(server));
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family =AF_INET;
server.sin_port = htons(20143);
/* connection */
status = connect(sockid ,(struct sockaddr *)&server, sizeof(struct sockaddr));
if (status == -1)
{
printf ("error in connection\n ");
}
else
{
printf("no error \n");
}
/* send*/
strcpy(buffer, "hello \n"),
printf("message: %s\n", buffer);
if(send(sockid, buffer ,strlen("buffer"),0) < 0 )
{
puts("sends failed");
return 1;
}
puts("data send");
/* receive
count1 = recv(sockid,,buf,0 );*/
if(recv(sockid, buffer1, 1024, 0) < 0 )
{
puts("receive failed ");
return 1;
}
puts("receive success");
puts(buffer1);
/*---- Print the received message ----*/
printf("Data received: %s",buffer1);
close (sockid);
}
server code is
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
struct sockaddr_in server ;
struct socklen_t ;
int s,sockid,status;
char buffer[1024];
char buffer1[1024];
/* socket */
sockid = socket(AF_INET, SOCK_STREAM,0);
if(sockid == -1)
{
printf("could not create socket");
}
{
printf(" socket created\n");
}
memset((char *)&server, 0, sizeof(server));
server.sin_addr.s_addr =inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(20143);
if((bind(sockid,(struct sockaddr *)&server, sizeof(struct sockaddr)))== -1)
{
puts("failure ");
return 1;
}
puts("success");
listen(sockid,5);
s = accept(sockid,(struct sockaddr *)&server, (socklen_t *)sizeof(server));
if(recv(sockid,buffer, 1024, 0)< 0 )
{
puts("receive failed ");
return 1;
}
puts("receive success");
puts(buffer1);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
enter code here
strcpy(buffer1,"Hello World\n");
if(send(sockid,buffer1,13,0) < 0 )
{
puts("failed ");
return 1;
}
puts("success");
close (sockid);
}
here i am trying to make two way connection between client and the server but i am unbale to finish it beacuse i am facing the problem of bind that is server did not bind with the client, every time it show error in binding . plz provide me the sufficient solution for that ..
Here you have a way to do sockets in "C", Comments are in Spanish but I hope it helps.
Link to my Github: https://github.com/MarcosAguayo/sockets-c
Client
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
/**
* Función que usa socket INET para conectarse con un servidor.
* #params char *hostServer, char *service
* #return res
*/
int abrirConexion (char *hostServer, char *service){
struct sockaddr_in dir;
struct servent *puerto;
struct hostent *host;
int res;
puerto = getservbyname (service, "tcp");
if(puerto == NULL) return -1;
host = gethostbyname (hostServer);
if(host == NULL) return -1;
dir.sin_family = AF_INET;
dir.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
dir.sin_port = puerto->s_port;
res = socket (AF_INET, SOCK_STREAM, 0);
if(res == -1) return -1;
if(connect (res, (struct sockaddr *)&dir, sizeof (dir)) == -1){
return -1;
}
return res;
}
/**
* Función para leer los datos del socket. Devuelve el total de bytes que
* ha leído, un -1 si da algun error o un 0 si se cierra.
* #params int fd, char *data, int longitud
* #return total
*/
int leerSocket (int fd, char *data, int longitud){
int total = 0;
int temp = 0;
// Validación de los parámetros de entrada
if ((fd == -1) || (data == NULL) || (longitud < 1)) return -1;
// Bucle que se ejecuta siempre que no hayamos leido todos los datos
while (total < longitud){
temp = read (fd, data + total, longitud - total);
if (temp > 0){
// Si se han leido los datos incrementamos la variable que después devolveremos
total = total + temp;
}else{
// Si devuelve 0, es que se ha cerrado el socket por lo que terminamos u devolvemos total
if (temp == 0) return total;
if (temp == -1){
switch (errno){
case EINTR:
case EAGAIN:
usleep (100);
break;
default:
return -1;
}
}
}
}
return total;
}
/**
* Escribe datos en el socket del cliente y devuelve el total de bytes que ha escrito
* #params int fd, char *data, int longitud
* #return num (Total bytes escritos) o -1
*/
int escribirSocket (int fd, char *data, int longitud){
int num = 0;
int temp = 0;
// Validar los parámetros
if ((fd == -1) || (data == NULL) || (longitud < 1)) return -1;
while (num < longitud){
temp = write (fd, data + num, longitud - num);
if (temp > 0){
num = num + temp;
}else{
if (temp == 0)
return num;
else
return -1;
}
}
return num;
}
/**
* Función MAIN
*/
void main (void){
int socketServer;
char cad[100];
// Abrimos la conexión con el server pasandole "localhost" y el nombre del servicio (/etc/services)
socketServer = abrirConexion ("localhost", "aguayo");
if (socketServer == 1){
printf ("No puedo establecer conexion con el servidor\n");
exit (-1);
}
strcpy(cad, "Hola");
escribirSocket(socketServer, cad, 5);
leerSocket (socketServer, cad, 6);
printf ("Hola buenas soy el cliente y he recibido: %s\n", cad);
close (socketServer);
}
Server
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
/**
* Función para aceptar la conexion del socket
* #param int res
* #return int ch
*/
int aceptarConexion (int res){
socklen_t long_cl;
struct sockaddr cl;
int ch;
long_cl = sizeof (cl);
ch = accept (res, &cl, &long_cl);
if (ch == -1)return -1;
return ch;
}
/**
* Función que usa socket INET
* #params char *servicio
* #return res
*/
int abrirConexion (char *servicio){
struct sockaddr_in dir;
struct sockaddr cl;
struct servent *puerto;
socklen_t long_cl;
int res;
res = socket (AF_INET, SOCK_STREAM, 0);
if (res == -1) return -1;
// obtenemos el servicio del fichero /etc/services
puerto = getservbyname (servicio, "tcp");
if (puerto == NULL) return -1;
// Se comletan los campos de la estructura
dir.sin_family = AF_INET;
dir.sin_port = puerto->s_port;
dir.sin_addr.s_addr =INADDR_ANY;
if (bind (res, (struct sockaddr *)&dir, sizeof (dir)) == -1){
close (res);
return -1;
}
if (listen (res, 1) == -1){
close (res);
return -1;
}
return res;
}
/**
* Función para leer los datos del socket. Devuelve el total de bytes que
* ha leído, un -1 si da algun error o un 0 si se cierra.
* #params int fd, char *data, int longitud
* #return num
*/
int leerSocket (int fd, char *data, int longitud){
int num = 0;
int temp = 0;
// Validación de los parámetros de entrada
if ((fd == -1) || (data == NULL) || (longitud < 1)) return -1;
// Bucle que se ejecuta siempre que no hayamos leido todos los datos
while (num < longitud){
temp = read (fd, data + num, longitud - num);
if (temp > 0){
num = num + temp;
}else{
if (temp == 0) return num;
if (temp == -1){
switch (errno){
case EINTR:
case EAGAIN:
usleep (100);
break;
default:
return -1;
}
}
}
}
return num;
}
/**
* Escribe datos en el socket del cliente y devuelve el total de bytes que ha escrito
* #params int fd, char *data, int longitud
* #return total (Total bytes escritos) o -1
*/
int escribirSocket (int fd, char *data, int longitud){
int total = 0;
int temp = 0;
// Validar los parámetros
if ((fd == -1) || (data == NULL) || (longitud < 1)) return -1;
while (total < longitud){
temp = write (fd, data + total, longitud - total);
if (temp > 0){
total = total + temp;
}else{
if (temp == 0) return total;
else return -1;
}
}
return total;
}
/**
* Función MAIN
*/
void main (void){
int socketServer;
int socketClient;
char cad[100];
socketServer = abrirConexion ("aguayo");
if (socketServer == -1){
printf ("No se puede abrir socket servidor\n");
exit (-1);
}
socketClient = aceptarConexion (socketServer);
if (socketServer == -1){
printf ("No se puede abrir socket de cliente\n");
exit (-1);
}
leerSocket (socketClient, cad, 5);
printf ("Soy el Servidor y he recibido: %s\n", cad);
strcpy (cad, "Adios");
escribirSocket (socketClient, cad, 6);
close (socketClient);
close (socketServer);
}
Related
In our project we have to make a game (that is already done) and allow a multiplayer way to play (with a P2P method). I have made "client" and "server" programs to begin (I think that in the future the programs will be the same) using the select method in order to allow them to send and receive messages to each other. When I tried to send a message (a number written in the terminal) from the server to the client, it's ok, but, when I tried to do the same from the client to the server, nothing happened. Moreover, when I start sending a message from the client to the server, it works but the server can't send nothing (more precisely the client doesn't receive anything).
I don't understand this behaviour, and so I've tried to use threads but my profesor said that I don't need it if I use well select...
You will find below the code for the "server"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#define FALSE 0
#define TRUE 1
typedef struct Element Element;
struct Element
{
int data_i;
Element *suivant;
};
typedef struct
{
Element *premier;
} File;
void initialise(File *file)
{
file->premier = NULL;
}
int enfiler(File *file, long long nbre)
{
if (file == NULL)
{
printf("Il faut initialiser la file");
return EXIT_FAILURE;
}
Element *new_el = malloc(sizeof(Element));
new_el->suivant = NULL;
new_el->data_i = nbre;
if (file->premier != NULL)
{
Element *elementActuel = file->premier;
while (elementActuel->suivant != NULL)
{
elementActuel = elementActuel->suivant;
}
elementActuel->suivant = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
else
{
file->premier = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
Element defiler(File *file)
{
if (file != NULL && file->premier != NULL)
{
Element *el = malloc(sizeof(Element));
el = file->premier;
file->premier = file->premier->suivant;
free (el);
return *el;
}
//voir quoi retourner lors d'erreurs
}
void stop(char * msg){
perror(msg);
exit(EXIT_FAILURE);
}
typedef struct {
int fd;
}client_info;
int main(int argc,char *argv[]){
//Variables
int opt = TRUE;
int master_socket=0, new_socket=0, max_client = 30, activity=0, i=0;
int max_sd = 0;
client_info client_tab[max_client];
struct sockaddr_in address;
int addr_len=0;
fd_set readfds;
long long message=0;
int64_t buffer=0;
int smess = 0;
int sd =0;
write(0,"initialisation\n",15);
//initializing the "file"
File file_mess, file_recus;
initialise(&file_mess);
initialise(&file_recus);
//Initializing files descriptors
for (i = 0; i < max_client; i++)
{
client_tab[i].fd = -1;
}
//create a master socket
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
//Initializing address
address.sin_family = AF_INET;
inet_aton("127.0.0.1", &address.sin_addr);
address.sin_port = htons( 1234 );
addr_len = sizeof(address);
//Configurating master_socket to listen to new connections .
if(bind(master_socket,(const struct sockaddr *)&address,addr_len)<0) stop("binding error");
if(listen(master_socket,3)<0) stop("Problem initializing master_socket");
printf("Enterring while\n");
while(TRUE){
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket, &readfds);
FD_SET(STDIN_FILENO,&readfds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_client ; i++)
{
//socket descriptor
sd = client_tab[i].fd;
//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd , &readfds);
//highest file descriptor number, need it for the select function
if(sd > max_sd)
max_sd = sd;
}
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
if ((activity < 0) && (errno!=EINTR)) stop("select error");
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addr_len))<0) stop("accepting problem");
for (i = 0; i < max_client; i++)
{
//if position is empty
if( client_tab[i].fd == -1 )
{
client_tab[i].fd = new_socket;
printf("Adding to list of sockets as %d\n\n" , i);
// Après avoir ajouté le client dans le tableau, le serveur lui renvoie un id (valeur de i)
if(send(client_tab[i].fd, &i, sizeof(int), 0) == -1) stop("recv() : envoi de l'id");
break;
}
}
}
//else its some IO operation on some other socket :)
for (i = 0; i < max_client; i++)
{
sd = client_tab[i].fd;
if (FD_ISSET( sd , &readfds) && sd!=-1)
{
//Check if it was for closing , and also read the incoming message
if ((smess = recv( sd,(char *)&buffer,__SIZEOF_LONG_LONG__,0)) == 0)
{
//Somebody disconnected , get his details and print
getpeername(sd , (struct sockaddr*)&address , (socklen_t*)&addr_len);
printf("%i disconnected.\n",i);
//Close the socket and mark as 0 in list for reuse
close( sd );
client_tab[i].fd = -1;
}
else{
message = ntohl(buffer);
buffer=0;
printf("Message reçu de %i : %lli\n",i,message);
enfiler (&file_recus, message);
message = 0;
}
}
}
if(FD_ISSET(STDIN_FILENO,&readfds)){
scanf("%lli",&message);
enfiler(&file_mess,message);
buffer = htonl(file_mess.premier->data_i);
for (i = 0; i < max_client; i++)
{
if(client_tab[i].fd != -1) send(client_tab[i].fd,&buffer,sizeof(buffer),0);
}
printf("J'ai bien envoyé : %lli\n",message);
defiler(&file_mess);
buffer = 0;
message=0;
}
if (file_mess.premier != NULL)
{
printf("regarde si des trucs à envoyer\n");
buffer = htonl(file_mess.premier->data_i);
//envoie à tout le monde
for (i = 0; i < max_client; i++)
{
if (client_tab[i].fd != -1)
{
send(client_tab[i].fd, &buffer, sizeof(buffer), 0);
}
}
printf("envoyé\n");
defiler(&file_mess);
buffer=0;
}
}
}
And here the "client" :
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFSIZE 100
#define TRUE 1
#define FALSE 0
typedef struct Element Element;
struct Element
{
int data_i;
Element *suivant;
};
typedef struct
{
Element *premier;
} File;
void initialise(File *file)
{
file->premier = NULL;
}
int enfiler(File *file, long long nbre)
{
if (file == NULL)
{
printf("Il faut initialiser la file");
return EXIT_FAILURE;
}
Element *new_el = malloc(sizeof(Element));
new_el->suivant = NULL;
new_el->data_i = nbre;
if (file->premier != NULL)
{
Element *elementActuel = file->premier;
while (elementActuel->suivant != NULL)
{
elementActuel = elementActuel->suivant;
}
elementActuel->suivant = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
else
{
file->premier = new_el;
printf("j'ai bien enfilé le message\n");
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
Element defiler(File *file)
{
if (file != NULL && file->premier != NULL)
{
Element *el = malloc(sizeof(Element));
el = file->premier;
file->premier = file->premier->suivant;
free(el);
return *el;
}
}
void stop(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
//Creating a TCP|IPV4 socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
stop("Probleme de socket");
//Creating the socket
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(1234);
inet_aton("127.0.0.1", &serv_addr.sin_addr);
//initializing the "file"
File file_mess, file_recus;
initialise(&file_mess);
initialise(&file_recus);
//initiliazing the file descriptor set
fd_set readfds;
FD_ZERO(&readfds);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
stop("Connection error");
int id = 0;
if(recv(sockfd, &id, sizeof(int), 0) == -1) stop ("recv() : reception de l'id"); // Le client récupère son id
printf("Mon id : %i\n", id);
FD_SET(sockfd, &readfds);
FD_SET(STDIN_FILENO, &readfds);
//Variables
int nSelect = 0;
int n;
long long mess = 0;
int64_t fmess = 0;
while (TRUE)
{
nSelect = select(sockfd + 1, &readfds, NULL, NULL, NULL);
if (nSelect < 0)
stop("Select error");
if (FD_ISSET(STDIN_FILENO, &readfds))
{
scanf("%lli", &mess);
fmess = htonl(mess);
send(sockfd, &fmess, sizeof(fmess), 0);
printf("J'ai bien envoyé : %lli\n", mess);
mess = 0;
}
if (file_mess.premier != NULL)
{
send(sockfd, &file_mess.premier->data_i, sizeof(file_mess.premier->data_i), 0);
defiler(&file_mess);
}
if (FD_ISSET(sockfd, &readfds))
{
printf("reçu\n");
if ((n=recv(sockfd, &mess, sizeof(long long), 0)) < 0)
stop("recv(");
else if (n==0)
{
printf("déconnexion...\n");
close(sockfd);
return EXIT_SUCCESS;
}
else
{
printf("cc\n");
mess = ntohl(fmess);
fmess = 0;
printf("Message reçu: %lli\n", mess);
enfiler(&file_recus, mess);
mess = 0;
}
}
}
exit(0);
}
Here, you will find my tests:
1-The client begins the conversation by sending 13, but doesn't receive what the server tries to send
client
server
2-Then, the server begins the conversation sending 15, the client doesn't receive it and he sends nothing
client, before stopping
server, before stopping
client, stopped
server, stopped
PS: the use of file is to allow a good treatment for the data (I will made a protocol [using long long numbers] and so I will have to process the data before sending and after receiving). And to finish, this code also permits to give a number to identify the players (and to know who the data receive is for).
In my code i try to do a little game (Nim) for a school project. So i use a server tcp and 2 threads to send info to the 2 clients.
I program step by step and i stuck here cause the client (on the th1 thread) doesn't display or receive the string "Joueur 1 entrez un nombre (1-3) : " in the function takeCoin.
server code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <semaphore.h>
#define false 0
#define true 1
int J[2] = {-1, -1};
int nCoin = 15;
sem_t semaphore;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int cree_socket_tcp_ip()
{
int sock;
struct sockaddr_in adresse;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "Erreur socket\n");
return -1;
}
memset(&adresse, 0, sizeof(struct sockaddr_in));
adresse.sin_family = AF_INET;
adresse.sin_port = htons(8080);
inet_aton("Localhost", &adresse.sin_addr);
if (bind(sock, (struct sockaddr*) &adresse, sizeof(struct sockaddr_in)) < 0)
{
close(sock);
fprintf(stderr, "Erreur bind\n");
return -1;
}
return sock;
}
void initCoin(char tab[])
{
tab[0] = '|';
tab[1] = ' ';
tab[2] = ' ';
tab[3] = ' ';
tab[4] = ' ';
for (int i = 5; i < 5 + nCoin;i++)
{
tab[i] = 'O';
}
tab[nCoin + 5] = ' ';
tab[nCoin + 6] = ' ';
tab[nCoin + 7] = ' ';
tab[nCoin + 8] = ' ';
tab[nCoin + 9] = '|';
tab[nCoin + 10] = '\n';
tab[nCoin + 11] = '\0';
}
void takeCoin(int sock, int coin)
{
char tCoin[3];
char tab[100];
int valid = false;
printf("In fonction takeCoin.\n");
while (valid == false)
{
if (J[0] == sock)
{
sprintf(tab,"Joueur 1 entrez un nombre (1-3) : ");
write(sock,tab,strlen(tab));
}
else
{
sprintf(tab,"Joueur 2 entrez un nombre (1-3) : ");
write(sock,tab,strlen(tab));
}
recv(sock,tCoin,3,0);
printf("tCoin : %s\n",tCoin);
coin = atoi(tCoin);
if ((coin > 0) && (coin <= 3))
valid = true;
else
{
sprintf(tab,"Le nombre doit être entre 1 et 3 bord inclus.\n");
write(sock,tab,46*sizeof(char));
}
}
}
void *func_j1(void *arg)
{
int sock = *((int *)arg);
int coin;
int nCoinT;
char tab[100];
char tCoin[3];
sprintf(tab,"Jeux des pièces.\n");
write(sock,tab,strlen(tab));
sprintf(tab,"Vous etes le joueur 1.\n");
write(sock,tab,strlen(tab));
sprintf(tab,"Attende du joueur 2.\n");
write(sock,tab,strlen(tab));
sem_wait(&semaphore);
sprintf(tab,"joueur 2 Trouver.\n");
write(sock,tab,strlen(tab));
sprintf(tab,"La partie commence.\n");
write(sock,tab,strlen(tab));
initCoin(tab);
write(sock,tab,strlen(tab));
pthread_mutex_lock(&mutex);
nCoinT = nCoin;
pthread_mutex_unlock(&mutex);
while (nCoinT >= 2)
{
takeCoin(sock, coin);
}
close(sock);
pthread_exit(NULL);
}
void *func_j2(void *arg)
{
int sock = *((int *)arg);
int nCoinT;
int coin;
char tab[100];
sprintf(tab,"Jeux des pièces.\n");
write(sock,tab,strlen(tab));
sem_post(&semaphore);
sprintf(tab,"Vous etes le joueur 2.\n");
write(sock,tab,strlen(tab));
sprintf(tab,"La partie commencer.\n");
write(sock,tab,strlen(tab));
initCoin(tab);
write(sock,tab,strlen(tab));
pthread_mutex_lock(&mutex);
nCoinT = nCoin;
pthread_mutex_unlock(&mutex);
while (nCoinT >= 2)
{
sprintf(tab,"Le joueur 1 est en train de jouer.\n");
write(sock,tab,strlen(tab));
sem_wait(&semaphore);
//takeCoin(sock, coin);
}
close(sock);
pthread_exit(NULL);
}
int affiche_adresse_socket(int sock)
{
struct sockaddr_in adresse;
socklen_t longueur;
longueur = sizeof(struct sockaddr_in);
if (getsockname(sock, (struct sockaddr*)&adresse, &longueur) < 0)
{
fprintf(stderr, "Erreur getsockname\n");
return -1;
}
printf("IP = %s, Port = %u\n", inet_ntoa(adresse.sin_addr), ntohs(adresse.sin_port));
return 0;
}
int main(void)
{
int sock_contact;
int sock_connectee;
int j;
pthread_t th1;
pthread_t th2;
struct sockaddr_in adresse;
socklen_t longueur;
sock_contact = cree_socket_tcp_ip();
if (sock_contact < 0)
return -1;
listen(sock_contact, 5);
printf("Mon adresse (sock contact) -> ");
affiche_adresse_socket(sock_contact);
sem_init (&semaphore, 0, 0);
while (1)
{
printf("Attende d'un client.\n");
longueur = sizeof(struct sockaddr_in);
sock_connectee = accept(sock_contact, (struct sockaddr*)&adresse, &longueur);
printf("Client trouver.\n");
printf("Client socket : %d\n",sock_connectee);
J[j] = sock_connectee;
if (j == 0)
pthread_create(&th1, NULL, func_j1, &sock_connectee);
else
pthread_create(&th2, NULL, func_j2, &sock_connectee);
j++;
}
return 0;
}
client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#define BUFFER_SIZE 256
int cree_socket_tcp_client(int argc, char** argv)
{
struct sockaddr_in adresse;
int sock;
if (argc != 3)
{
fprintf(stderr, "Usage : %s adresse port\n", argv[0]);
exit(0);
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "Erreur socket\n");
return -1;
}
memset(&adresse, 0, sizeof(struct sockaddr_in));
adresse.sin_family = AF_INET;
adresse.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &adresse.sin_addr);
if (connect(sock, (struct sockaddr*) &adresse, sizeof(struct sockaddr_in)) < 0)
{
close(sock);
fprintf(stderr, "Erreur connect\n");
return -1;
}
return sock;
}
void *fRecv(void *arg)
{
int sock = *((int *)arg);
int len;
char msg[100];
while((len = recv(sock,msg,100,0)) > 0)
{
msg[len] = '\0';
printf("%s",msg);
}
}
void *fSend(void *arg)
{
int sock = *((int *)arg);
int len;
char msg[100];
while (1)
{
fgets(msg,100,stdin);
len = write(sock,msg,strlen(msg));
if(len < 0)
printf("\n message not sent \n");
}
}
int main(int argc, char **argv)
{
int sock=cree_socket_tcp_client(argc, argv);
int i = 0;
pthread_t tRecv;
pthread_t tSend;
char tab[100];
char tab2[100];
char fin[4] ="fin";
pthread_create(&tRecv, NULL, fRecv, &sock);
pthread_create(&tSend, NULL, fSend, &sock);
pthread_join(tRecv, NULL);
close(sock);
}
I program on a virtual machine, I don't know if it matters.
first question asked on SO. Not an eng native so coulda make some error, and my comments are in Italian.
Currently having a problem with my C Server implementation. The code run without errors, but when i excute it, it just shows nothing. I have tried to breaking down the code and placing some prints to shows where it "block" but can't reach a conclusion. Here's the code:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
struct sockaddr_in address;
struct sockaddr_in local;
//definisco la struttura per gli header composta dal nome e dal valore
struct header {
char * nome;
char * valore;
};
struct header h[100];
int main() {
printf("qui");
int s; //istanza del socket
int newS; //istanza del socket del server
int newS2; //socket per la connessione al client
int site; //istanza file ricevuti
int conn_max = 10; //istnza connessionni massime server
char request[1000]; //istanza della response
int primiduepunti = 0;
int sin_size = 0;
int j = 0; //contatore
int i = 0; //contatore
s = socket(AF_INET, SOCK_STREAM, 0); //creazione socket
//Configurazione indirizzo IP locale
((char *)&local.sin_addr)[0] = 127;
((char *)&local.sin_addr)[1] = 0;
((char *)&local.sin_addr)[2] = 0;
((char *)&local.sin_addr)[3] = 1;
local.sin_family = AF_INET;
local.sin_port = htons(1050);
newS = bind(s, (struct sockaddr*)&local, sizeof(struct sockaddr_in)); //assegna un indirizzo locale ad un socket
if( newS == -1) {
perror("Bind fallita");
return 1;
}
newS = listen(s, conn_max); //metto in ascolto il nostro server
while(1) {
sin_size = sizeof(struct sockaddr_in);
printf("qua");
newS2 = accept(s,(struct sockaddr*)&local, &sin_size); //Crea un nuovo socket che è connesso al client
printf("Accettata connessione con client \n");
fflush(stdout);
if(fork == 0) {
if(newS2 == -1) {
perror("Accept fallita");
return 1;
}
}
h[0].nome = request;
h[0].valore = h[0].nome;
//ciclo per riempire gli header; read ritorna il numero di elementi letti
for(i = 0, j = 0; (newS = read(newS2, request+i, 1)) >0; i++) {
if((i>1) && (request[i] == '\r') && (request[i+1] == '\n')) {
primiduepunti = 1;
request[i] = 0;
if(h[j].nome[0] == 0) break;
h[++j].nome = request+i+2;
}
if(primiduepunti && j>0 && request[i] == ':') {
primiduepunti = 0;
h[j].valore = request+i+1;
request[i] = 0;
}
}
for(int i=1; i<j; i++) {
printf("%s ---> %s \n", h[i].nome, h[i].valore);
}
}
}
Thanks for all the help!
Some logic problem, look:
while(1) {
sin_size = sizeof(struct sockaddr_in);
printf("qua");
newS2 = accept(s,(struct sockaddr*)&local, &sin_size);
printf("Accettata connessione con client \n");
fflush(stdout);
if(fork == 0) {
if(newS2 == -1) {
perror("Accept fallita");
return 1;
}
}
}
Whatever happens you return to accept or exits, there is no condition that lets you get out the loop to read something. return 1 just returns from main and exits the program.
Note: I suppose fork is a call to fork(), but even in that case problem is the same...
Something like this should be better:
while(1) {
sin_size = sizeof(struct sockaddr_in);
newS2 = accept(s,(struct sockaddr*)&local, &sin_size);
if(newS2 == -1) {
perror("Accept fallita");
return 1;
}
printf("Accettata connessione con client \n");
fflush(stdout);
if(fork() == 0) {
break; // get out the loop...
}
}
I am trying to do a chatroom where I have a server and multi clients, but I have a problem, when I execute my code of server (serverCHAT.c), I have a problem with the bind connection. I don't know why.
When I execute the program, the if sentence of a bind problems appears on the console.
I check the connection, but I can not find the error.
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdio.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define MAX_CLIENT 10
/*
BIBLIOGRAFIA:
https://github.com/yorickdewid/Chat-Server
comando linux ip: ifconfig es : inet addr
*/
int totcltes=0;
int client_sockfd[MAX_CLIENT];
void *coneccion_clte(void *arg);
int clientes_conectados[MAX_CLIENT];
static unsigned int cli_count = 0;
static int uid = 10;
/* Cliente */
typedef struct {
struct sockaddr_in addr; /* Client remote address */
int connfd; /* Connection file descriptor */
int uid; /* Client unique identifier */
char name[32]; /* Client name */
} client_t;
client_t *clients[MAX_CLIENT];
/* agregar cliente a la cola */
void queue_add(client_t *cl){
int i;
for(i=0;i<MAX_CLIENT;i++){
if(!clients[i]){
clients[i] = cl;
return;
}// if
}// for
}// agregar cliente
/* quitar cliente de la cola */
void queue_delete(int uid){
int i;
for(i=0;i<MAX_CLIENT;i++){
if(clients[i]){
if(clients[i]->uid == uid){
clients[i] = NULL;
return;
}// if
}// if
}// for
}// quitar cola
/* Senviar mensaje */
void enviar_mensaje(char *s){
int i;
for(i=0;i<MAX_CLIENT;i++){
if(clients[i]){
write(clients[i]->connfd, s, strlen(s));
}// if
}// for
}// enviar mensaje
/* Handle all communication with the client */
void *coneccion_clte(void *arg){
char buff_out[1024];// mensaje de salida
char buff_in[1024]; // mensaje de entrada
int rlen; // longitu del mensaje
cli_count++; //aumentamos en uno el cliente
client_t *cli = (client_t *)arg;
printf("Cliente Aceptado %d ", cli->uid);
/* Recibiendo mensaje */
while((rlen = read(cli->connfd, buff_in, sizeof(buff_in)-1)) > 0){
buff_in[rlen] = '\0';
buff_out[0] = '\0';
/* Special options */
if(strncmp("exit",buff_in,4==0)){
break;
}else{
sprintf(buff_out, "[%s]: %s\n", cli->name, buff_in);
enviar_mensaje(buff_out);
}//else
}//while
/* Cerrar al conexion */
close(cli->connfd);
/* Delete client from queue and yeild thread */
queue_delete(cli->uid);
printf("Fin del chat :c ");
free(cli);
cli_count--;
//pthread_detach(pthread_self());
return NULL;
}//coneccion_clte
int main()
{
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
int server_sockfd ;// listenfd
//int listenfd = 0;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//int parametro[MAX_CLIENT];
//pthread_t tid[MAX_CLIENT];
//int i;
pthread_t tid;
int connfd = 0; //para obtener el descriptor de archivo (connection file descriptor y saber que hilo es)
/* configuracion del socket*/
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
//listenfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
/*
bind()
Avisa al SO que hemos abierto un socket y asociamos nuestro programa a este socket
*/
//bind(server_sockfd,(struct sockaddr *)&server_address,server_len);
if(bind(server_sockfd, (struct sockaddr *)&server_address,sizeof(serv_addr)) < 0);{
printf("Error: bind \n");
//return 1;
}//if bind
/*
Crear una cola de conexiones
Listen
Indicamos al programa que empiece a escuchar peticiones y las registre
*/
if(listen(server_sockfd, 5) < 0){
printf("Error: Listen");
//return 1;
}//is listen
printf("<[Servidor Inicializado :D]>\n");
/* Aceptar clientes */
while(totcltes<MAX_CLIENT){
connfd = accept(server_sockfd, (struct sockaddr*)&client_address, &client_len);
/* Revisar el Total de clientes */
if((cli_count+1) == MAX_CLIENT){
printf("Clientes Maximos Alcanzados \n");
close(connfd);
continue;// para que revise la siguiente iteracion
}// if
/* Configuracion del cliente */
client_t *cli = (client_t *)malloc(sizeof(client_t));// creamos la estructura cliente cli
cli->addr = client_address;
cli->connfd = connfd;
cli->uid = uid++;
sprintf(cli->name, "%d", cli->uid);
/* Agregar clientes a la cola */
queue_add(cli);
pthread_create(&tid, NULL, &coneccion_clte, (void*)cli);
}//while aceptar clientes
}//main
You are using sizeof(serv_addr) as the length specifier instead of server_len.
You are declaring server_len as an int: it should be socklen_t.
You are doing the same thing with client_len: it should be socklen_t.
Please go back and study the original code from githu. It actually works.
I'm sorry but I'm a beginner in C Socket Programming. I have a Server and more client. When a Client send a message to the Server, the Server should forward this message to all Clients.
I designed Server and Client using the Select(), now I don't know how I can do to send in broadcast the message to all Clients, in broadcast way.
This is my Server side called SelectServer.c:
#include "Header.h"
#include "Utility.h"
/**
variabili globale client sockets array
rappresenta l'array di socket descriptor connessi ai client TCP
*/
int conn_set[SIZE];
/**
#brief aggiunge la nuova connessione all'array di client connessi
#param sockfd, il socket della nuova connessione
#param conn_set, ptr all'array delle connessioni
#param dim, dimensione dell'array
#return true se la nuova connessione è stata registrata, false se la coda è piena
*/
bool add_client(int sockfd, int *conn_set, int dim){
int i = 0;
bool is_registered = false;
for (i = 0; i < dim; i++)
{
if (conn_set[i] == -1)
{
conn_set[i] = sockfd;
is_registered = true;
break;
}
}
return is_registered;
}
/**
#brief Funzione che gestisce l'arrivo di nuove connessioni sul listening socket TCP.
#param sockT - listening TCP socket del server
#return intero:
-# pari a -1 se la connessione è stata rifiutata.
-# pari al socket descriptor della nuova connessione (se correttamente inserita in elenco)
*/
int handleNewConn(int sockT){
struct sockaddr_storage client;
socklen_t sslen = sizeof(client);
int conn = accept(sockT, (struct sockaddr *)&client, &sslen);
if (conn == -1)
{
perror("accept() error: ");
return -1;
}
printf("TCP listening socket accepted new connection from ");
printAddressInfo((struct sockaddr *)&client, sslen);
printf("\n");
bool is_added = add_client(conn, conn_set, SIZE);
if (is_added == false)
{
printf("max client queue\n");
close(conn);
return -1;
}
return conn;
}
/**
#brief Inizializza l'array dei socket connessi
#param conn_set, ptr all'arrayd di interi
#param dim, dimensione dell'array
*/
void setConnSet(int *conn_set, int dim){
int i = 0;
for (i = 0; i < dim; i++)
{
conn_set[i] = -1;
}
}
/**
#brief Funzione di utilità
#param name, nome dell'eseguibile
*/
void usage(char *name){
printf("Usage: %s <domain>\n", name);
printf("\tdomain: 0 (UNSPEC), 4 (INET), 6 (INET6)\n");
}
int main(int argc, char *argv[]){
//*********************
char buf2[50000];
int posxy[2];
int pos[100][100];
int x, y;
//*********************
if (argc != 2)
{
usage(argv[0]);
return INVALID;
}
int family = getFamily(argv[1]);
int sockT = 0; //TCP listening socket
int sockU = 0; //UDP listening socket
sockT = passiveOpen(family, NULL, SERVICEPORT, SOCK_STREAM);
sockU = passiveOpen(family, NULL, SERVICEPORT, SOCK_DGRAM);
if ((sockT == -1) || (sockU == -1))
{
printf("Errore nell'avviare i socket\n");
return ERROR;
}
/* su Mac OS X:
$ netstat -a | grep 49152
tcp4 0 0 *.49152 *.* LISTEN
udp4 0 0 *.49152 *.*
*/
printf("TCP Server and UDP server running on port %s\n", SERVICEPORT);
//inizializzo l'array
setConnSet(conn_set, SIZE);
//handle delle nuove connessioni (socket connessi)
int conn = 0;
//protocol-independent management of connections
struct sockaddr_storage client;
socklen_t sslen = sizeof(client);
/*
definiamo il set dei file descriptor da monitorare:
il server sarà in attesa di:
- connessioni
- messaggi,
- e tutte condizioni monitorabili in lettura
*/
//dichiaro 2 read file descriptor set
fd_set rset, allset;
FD_ZERO(&rset); //azzero set descrittori
FD_ZERO(&allset); //azzero set descrittori copia
FD_SET(sockT, &rset); //aggiungo socket TCP
FD_SET(sockU, &rset); //aggiungo socket UDP
//prendo il max tra i 2, più 1
int max = (sockT > sockU)?sockT+1: sockU+1;
//duplico il set - allset contiene sempre i 2 socket TCP ed UDP
allset = rset;
//***************
ssize_t n = 0;
//***************
int result = 0;
int quit = 0;
while (!quit)
{
/*
rfds è un value-result argument, modificato da select():
dobbiamo re-inizializzarlo
*/
FD_ZERO(&rset);
rset = allset;
//wait for select forever
result = select(max, &rset, NULL, NULL, NULL);
if (result == -1)
{
perror("select() error: ");
continue;
}
else if (result == 0)
{
//timeout su select (non specificato, non dovrei mai arrivarci)
continue;
}
else
{
//result è pari al numero di descriptor pronti in lettura...
printf("%d socket ready for reading\n", result);
//verifichiamo chi ha dati da leggere...
if ( FD_ISSET(sockU, &rset))
{
//*******
n = recv(sockU, posxy, sizeof(posxy), 0);
printf ("Prova %d",posxy[0]);
//******
printf("Received a datagram...\n");
handleUDPMessage(sockU);
//printf("decrement result...\n");
result--;
}
if ( FD_ISSET(sockT, &rset))
{
//new TCP Connection
conn = handleNewConn(sockT);
if (conn != -1)
{
//printf("add new conn to allset\n");
FD_SET(conn, &allset);
if ( (conn + 1) > max)
max = conn+1;
}
result--;
}
if (result == 0)
{
//skip the rest
continue;
}
//a questo punto devo controllare tutte le connessioni attive dei client
int j = 0; //indice dell'array di connessioni TCP client
while (result > 0)
{
if ( (conn_set[j] != -1) && FD_ISSET(conn_set[j], &rset))
{
printf("Client Connection number %d ready for reading ...\n", j);
int status = handleTCPClient(conn_set[j]);
//decremento result
result--;
if (status == 0)
{
//client ha chiuso la connessione
close(conn_set[j]);
//rimuovo il socket dal set da monitorare
FD_CLR(conn_set[j], &allset);
//libero la sua posizione nell'array
conn_set[j] = -1;
}//fi status
}//fi FD_ISSET
//passo al prossimo elemento dell'array di connessioni TCP
j++;
}//wend client connection
}//fi result
}//wend
//never here
close(sockT);
close(sockU);
return 0;
}
This is my Client side called SelectClient.c:
#include "Header.h"
#include "Utility.h"
/**
#brief Utility function
#param name, nome dell'eseguibile
*/
void usage(char *name){
printf("Usage: %s <servername> <protocol> <domain>\n", name);
printf("\tprotocol= TCP aut UDP;\n");
printf("\tdomain= 0 (UNSPEC), 4(INET), 6(INET6)\n");
}
/**
#brief Esegue l'I/O multiplexing su stdin e socket connesso (UDP/TCP)
#param sock, il socket da monitorare
#param type, tipo di socket
#return nulla
*/
void multiplex(int sock, int type){
//*******************************
int pos[100][100];
int posxy[2];
int x,y,xx,yy;
char movimento;
for(x=0;x<100;x++)
for(y=0;y<100; y++)
pos[x][y]=0;
time_t tt;
/* Intializes random number generator */
srand((unsigned) time(&tt));
xx = rand() % 50;
yy = rand() % 50;
printf("xx vale %d, yy vale %d",xx,yy);
pos[xx][yy] = 1;
printf("MAPPA INIZIALE:\n");
for(x=0;x<100;x++)
for(y=0;y<100; y++)
printf("%d",pos[x][y]);
//*******************************
printf("Insert messages for server\n");
fd_set rset;
FD_ZERO(&rset);
FD_SET(STDIN_FILENO, &rset);
FD_SET(sock, &rset);
int max = (sock > STDIN_FILENO)? sock: STDIN_FILENO;
struct timeval timer;
timer.tv_sec = 5;
timer.tv_usec = 0;
int result = 0;
bool quit = false;
//predispongo la comunicazione ed il file descriptor set da monitorare
ssize_t n = 0;
char msg[BUFSIZE] = "";
//***********************************
int msgpos[100][100];
char msgposc[50000] = "";
//***********************************
while (!quit)
{
result = select(max+1, &rset, NULL, NULL, &timer);
if (result == -1)
{
perror("select() error: ");
break;
}
if (result == 0)
{
//printf("select timeout\n");
}
if (result > 0)
{
if (FD_ISSET(STDIN_FILENO, &rset))
{
if (fgets(msg, BUFSIZE-1, stdin) != NULL)
{
//**************************
printf("scrivi\n");
//scanf("%c",&movimento);
movimento = getchar();
printf("movimento %c\n",movimento);
if(movimento == 'j'){
printf("destra\n");
pos[xx][yy] = 0;
yy++;
printf("xx vale %d, yy vale %d",xx,yy);
pos[xx][yy] = 1;
}
else if(movimento == 'h'){
printf("sinistra\n");
pos[xx][yy] = 0;
yy--;
printf("xx vale %d, yy vale %d",xx,yy);
pos[xx][yy] = 1;
}
else if(movimento == 'u'){
printf("sopra\n");
pos[xx][yy] = 0;
xx++;
printf("xx vale %d, yy vale %d",xx,yy);
pos[xx][yy] = 1;
}
else if(movimento == 'n'){
printf("sotto\n");
pos[xx][yy] = 0;
xx--;
printf("xx vale %d, yy vale %d",xx,yy);
pos[xx][yy] = 1;
}
else
printf("Non hai inserito un comando valido\n");
for(x=0;x<100;x++)
for(y=0;y<100; y++)
printf("%d",pos[x][y]);
//snprintf(msgposc, 50000, "%d", pos);
//snprintf(posx, 10, "%d", xx);
//snprintf(posy, 10, "%d", yy);
//printf("PROVAaa: %s \n", posx);
posxy[0] = xx;
posxy[1] = yy;
//**************************
/*
fgets ritorna una stringa che termina con la sequenza
'\n\0'
il null-terminated non è contato da strlen,
ma '\n' si.
Per tagliare '\n' trasmetto (strlen(msg) - 1).
#note: ATTENZIONE
Ogni volta che premo "Return" (dò invio), fgets() ritorna una stringa è vuota.
La stringa vuota viene letta da send che trasmette 0 bytes dal socket "sock".
Dobbiamo distinguere 2 casi:
- se sock è di tipo SOCK_STREAM, l'operazione non genera dati da trasmettere;
- se sock è di tipo SOCK_DGRAM, l'operazione genera un datagram UDP vuoto, che viene inviato al server UDP
Per eliminare questo scenario, possiamo effettuare send solo su stringhe non vuote.
*/
//if ( (strlen(msg) - 1) != 0){
n = send(sock, posxy, sizeof(posxy), 0);
//n = send(sock, msg, strlen(msg) - 1, 0);
printf("sent %d bytes\n", (int)n);
//}//fi
}
else
break; //chiusura
}
if (FD_ISSET(sock, &rset))
{
//n = recv(sock, msg, BUFSIZE-1, 0);
//******************************
n = recv(sock, posxy, sizeof(posxy), 0);
//*******************************
if (n == -1)
{
perror("recv() error: ");
close(sock);
return; // ERROR;
}
else if (n > 0)
{
//**************************
msg[n] = 0;
msgpos[n][n]=0;
printf("mappa:\n");
printf("server reply: '%d'\n", posxy[0]);
//**************************
// msg[n] = 0;
// printf("\tResponse %d bytes message '%s'\n", (int)n, msg);
}
else
{
//n==0 over TCP: closed connection
//if (type == SOCK_STREAM)
// break;
/*
In realtà non abbiamo necessità di usare il parametro type in input alla funzione,
perché il tipo del socket può essere ottenuto leggendo le opzioni del socket:
*/
int sockType = 0;
socklen_t optlen = sizeof(sockType);
if ( getsockopt(sock, SOL_SOCKET, SO_TYPE, &sockType, &optlen) == 0){
if (sockType == SOCK_STREAM) {
printf("This is a TCP socket that received a FIN segment\n");
break;
} else {
printf("This is an UDP socket that received an empty datagram\n");
}
}//fi getsockopt
}
}//fi sock
}//fi result
FD_ZERO(&rset);
FD_SET(STDIN_FILENO, &rset);
FD_SET(sock, &rset);
max = (sock > STDIN_FILENO)? sock: STDIN_FILENO;
timer.tv_sec = 5;
timer.tv_usec = 0;
}//wend
printf("Multiplex ended\n");
}
int main(int argc, char *argv[]){
if (argc != 4)
{
usage(argv[0]);
return INVALID;
}
int family = getFamily(argv[3]);
int type = 0;
if ((strcmp(argv[2], "TCP") == 0) || (strcmp(argv[2],"tcp") == 0))
{
type = SOCK_STREAM;
}
else if (strcmp(argv[2], "UDP") == 0 || (strcmp(argv[2],"udp") == 0))
{
type = SOCK_DGRAM;
}
else
{
printf("Invalid service type\n");
return FAILURE;
}
int sockfd = open_socket(family, argv[1], SERVICEPORT, type);
if (sockfd == INSUCCESS)
{
printf("Errore nell'aprire il socket e stabilire la connessione al server (TCP only)\n");
return ERROR;
}
//ho un socket CONNESSO verso la destinazione specificata:
struct sockaddr destination;
socklen_t len = sizeof(destination);
int res = getpeername(sockfd, &destination, &len);
if (res != 0) {
close(sockfd);
return FAILURE;
}
//visualizzo il remote address
printf("Connected to remote address: ");
printAddressInfo(&destination, len);
printf("\n");
multiplex(sockfd, type);
printf("Closing the socket...\n");
close(sockfd);
return 0;
}
This is Utility.c (where are implemented some functions):
/**
#addtogroup Group11
#{
*/
/**
#file Utility.c
#author Catiuscia Melle
#brief Implementazione di funzioni di utilità.
*/
#include "Utility.h"
void printAddressInfo(struct sockaddr * addr, socklen_t len){
//no reverse lookup in getnameinfo
int niflags = NI_NUMERICSERV | NI_NUMERICHOST;
char IP[INET6_ADDRSTRLEN] = "";
char port[PORT_STRLEN] = "";
//visualizzo l'indirizzo locale del socket
int rv = getnameinfo(addr, len, IP, INET6_ADDRSTRLEN, port, PORT_STRLEN, niflags);
if (rv == 0)
{
printf("'%s:%s'", IP, port);
}
else
{
printf("getnameinfo() error: %s\n", gai_strerror(rv));
}
}
int open_socket(int family, char *hostname, char *servicename, int type){
int sockfd = 0; //valore di ritorno della funzione
int result = 0;
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints)); //azzero hints
hints.ai_family = family; //richiedo la risoluzione per IPv6
hints.ai_socktype = type; //service type
/*
Se richiedo AF_INET6 come family,
allora specificando il flag AI_V4MAPPED,
getaddrinfo() deve ritornare l'IPv4-mapped IPv6 address
se non trova indirizzi IPv6.
Diversamente, l'opzione non è presa in considerazione
*/
hints.ai_flags = AI_V4MAPPED;
result = getaddrinfo(hostname, servicename, &hints, &res);
if (result != 0)
{
printf("getaddrinfo: %s\n", gai_strerror(result));
return INSUCCESS;
}
printf("Resolution for: %s:%s Done!\n", hostname, servicename);
for (p = res; p != NULL; p = p->ai_next)
{
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd == -1)
{
perror("socket() error: ");
continue;
}
//TCP o UDP, il socket viene comunque connesso al destination address
result = connect(sockfd, p->ai_addr, p->ai_addrlen);
if (result == -1)
{
perror("connect() error: ");
close(sockfd);
continue;
}
break;
}//for
if (p == NULL) //if (!p)
{
printf("Connessione al server %s:%s fallita\n", hostname, servicename);
return INSUCCESS;
}
//dealloco risorse resolver
freeaddrinfo(res);
return sockfd;
}
int getFamily(char *param){
int family = 0;
if (strncmp(param, "4", 1) == 0){
family = AF_INET;
} else if (strncmp(param, "6", 1) == 0){
family = AF_INET6;
} else {
family = AF_UNSPEC;
}
return family;
}
/*************************************************************************/
int passiveOpen(int family, char *nodename, char *servicename, int socktype) {
int sock = INSUCCESS;
int result = 0;
struct addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = socktype;
hints.ai_flags |= AI_V4MAPPED;
hints.ai_flags |= AI_NUMERICSERV;
result = getaddrinfo(nodename, servicename, &hints, &res);
if (result != 0)
{
printf("getaddrinfo: %s\n", gai_strerror(result));
return INSUCCESS;
}
int reuse = 1; //opzione SO_REUSEADDR
for (p = res; p != NULL ; p = p->ai_next)
{
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sock == -1)
{
perror("socket() error: ");
continue;
}
/*
Per un socket nel dominio AF_INET6, se l'opzione IPV6_V6ONLY è abilitata
viene meno la compatilibità con IPv4: il socket accetterà comunicazioni solo se
provenienti da nodi IPv6 (ritornando l'errore 'connection refused' al client che
cerca di connettersi).
Altrimenti, al socket sono consegnati anche datagram IPv4.
Per abilitare l'opzione:
*/
int v6flag = 1;
if (v6flag == 1)
{
//turn-on V6ONLY option
if (p->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6flag, sizeof(v6flag)) < 0)
{
close(sock);
continue;
}
}
if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0 )
{
perror("setsockopt() error: ");
continue;
}
result = bind(sock, p->ai_addr, p->ai_addrlen);
if (result == -1)
{
perror("bind() error: ");
close(sock);
continue;
}
break;
}//for
if (p == NULL)
{
printf("Non siamo riusciti ad avviare il server %s:%s per il servizio %d\n", nodename, servicename, socktype);
sock = INSUCCESS;
}
//dealloco le risorse
freeaddrinfo(res);
if (socktype == SOCK_STREAM)
{
//TCP passive open
result = listen(sock, BACKLOG);
if (result == -1)
{
perror("listen() error: ");
close(sock);
return INSUCCESS;
}
}
return sock;
}
void handleUDPMessage(int sockU){
//protocol-independent addresses management
struct sockaddr_storage client;
socklen_t sslen = sizeof(client);
char msg[BUFSIZE] = "";
ssize_t n = 0;
int posxy[2];
//n = recvfrom(sockU, msg, BUFSIZE-1 , 0, (struct sockaddr *)&client, &sslen);
//*******************
n = recvfrom(sockU, posxy, sizeof(posxy), 0, (struct sockaddr *)&client, &sslen);
//*****************
if (n < 0)
{
perror("error on recvfrom(): ");
return;
}
printAddressInfo((struct sockaddr *)&client, sslen);
msg[n] = '\0';
//printf("Received UDP %d bytes message '%s'\n", (int)n, msg);
printf("Received UDP %d bytes message '%d'\n", (int)n, posxy[0]);
char c = toupper(msg[n-1]);
msg[n-1] = toupper(msg[0]);
msg[0] = c;
printf("Reply to msg\n");
//n = sendto(sockU, msg, strlen(msg), 0, (struct sockaddr *)&client, sslen);
n = sendto(sockU, posxy, sizeof(posxy), 0, (struct sockaddr *)&client, sslen);
if (n == -1)
{
perror("sendto() error: ");
}
return;
}
int handleTCPClient(int sock){
char msg[BUFSIZE] = "";
ssize_t n = 0;
int posxy[2];
//get the message from client
//n = recv(sock, msg, BUFSIZE-1, 0);
n = recv(sock, posxy, sizeof(posxy), 0);
if (n > 0)
{
//protocol-independent management of connections
struct sockaddr_storage client;
socklen_t sslen = sizeof(client);
char ipstr[INET6_ADDRSTRLEN] = "";
char portstr[INET6_ADDRSTRLEN] = "";
getpeername(sock, (struct sockaddr *)&client, &sslen);
int niflags = NI_NUMERICSERV | NI_NUMERICHOST;
int res = getnameinfo( (struct sockaddr *)&client, sslen, \
ipstr, INET6_ADDRSTRLEN, portstr, INET6_ADDRSTRLEN, niflags);
if (res == 0)
{
printf("Received TCP message from client da %s:%s\n", ipstr, portstr);
}
msg[n] = '\0';
//printf("\tmessage '%s'\n\t%d bytes\n", msg, (int)n);
printf("\tmessage '%d'\n\t%d bytes\n", posxy[0], (int)n);
msg[0] = toupper(msg[0]);
msg[n/2] = toupper(msg[n/2]);
msg[n-1] = toupper(msg[n-1]);
//n = send(sock, msg, strlen(msg), 0);
n = send(sock, posxy, sizeof(posxy), 0);
if (n == -1)
{
perror("send() error: ");
}
return 1;
}
if (n == 0)
{
printf("il client ha chiuso la connessione\n");
return 0;
}
if (n < 0)
{
perror("error on recv(): ");
return -1;
}
return -1;
}
and these are my libraries called Utility.h and Header.h:
/**
#addtogroup Group11
#{
*/
/**
#file Utility.h
#author Catiuscia Melle
#brief Interfaccia del modulo di funzioni di utilità.
*/
#ifndef __UTILITY_H__
#define __UTILITY_H__
#include "Header.h"
/**
#brief Utility function per la visualizzazione dell'indirizzo associato ad un socket,
protocol-independent
#param addr, ptr alla struct sockaddr da leggere
#param len, dimensione della struttura puntata da addr
#return nulla
*/
void printAddressInfo(struct sockaddr * addr, socklen_t len);
/**
#brief Utility per l'apertura di un connection socket TCP IPv6
#param family - ipv4 o ipv6 protocol family domain...
#param hostname - stringa contenente l'hostname per cui è invocato il resolver
#param servicename - stringa contenente il service name per cui è invocato il resolver
#param type - intero pari al tipo di socket SOCK_STREAM o SOCK_DGRAM
#return intero, pari al socket descriptor creato (-1 in caso di errore).
Attenzione, restituisce sempre un socket connesso (UDP e TCP)
*/
int open_socket(int family, char *hostname, char *servicename, int type);
/**
#brief Legge il valore di param e ritorna l'Address Family corrispondente
#param param, contiene il valore di argv[] corrispondente al dominio inserito.
#return il valore di Address Family corrispondente al dominio specificato
*/
int getFamily(char *param);
/**
#brief Funzione per la hostname resolution che ritorna il socket descriptor per un server.
#param nodename - hostname da risolvere
#param servicename - indirizzo del servizio
#param socktype - tipo di sock (SOCK_STREAM, SOCK_DGRAM)
#return intero pari al socket descriptor allocato o -1 in caso di errore
*/
int passiveOpen(int family, char *nodename, char *servicename, int socktype);
/**
#brief Funzione che gestisce l'arrivo di messaggi sul socket UDP in ascolto
#param sockU - socket UDP in ascolto
#return nulla
Effettua ricezione ed invio al client UDP. Usa <em>getnameinfo()</em> per recuperare
l'indirizzo del client UDP.
*/
void handleUDPMessage(int sockU);
/**
#brief Funzione che gestisce l'arrivo di nuovi messaggi su connessioni TCP.
#param sock - socket TCP della connessione client pronta.
#return intero:
-# pari a -1 in caso di errore;
-# pari a 0 se la connessione è stata chiusa;
-# pari a 1 se il messaggio è stato elaborato con successo.
*/
int handleTCPClient(int sock);
#endif
/** #} */
/**
#addtogroup Group11
#{
*/
/**
#file Header.h
#author Catiuscia Melle
#brief Header comune al client e server dell'esempio
L'header definisce costanti comuni al client e server.
*/
#ifndef __HEADER_H__
#define __HEADER_H__
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> //resolver related functions
#include <sys/types.h> //necessario su Mac
#include <stdlib.h>
#include <ctype.h> //toupper()
#include <stdbool.h>
#define PORTNUMBER 49152 /**< TCP listening port, decimal */
#define SERVICEPORT "49152" /**< TCP listening port, name */
#define PORT_STRLEN 6 /**< lunghezza di una stringa rappresentativa di un indirizzo di trasporto */
#define BACKLOG 10 /**< dimensione della coda di connessioni */
#define SIZE 15 /**< dimensione della coda di connessioni concorrenti gestite dal server */
#define BUFSIZE 512 /**< dimensione del buffer di messaggio */
#define FAILURE 3 /**< definizione del valore di errore di ritorno del processo in caso di errori delle Sockets API */
#define INVALID 5 /**< se i due processi non sono avviati col giusto numero di parametri */
#define ERROR 1 /**< valore di errore */
#define INSUCCESS -1 /**< valore di ritorno non valido */
#endif /* __HEADER_H__ */
/** #} */
In particular, look that the message that I send from Client to Server is called "posxy". The Server receive "posxy", print it and send it again to the client who sent. But if I open more Client, the Server send "posxy" only at the Client who sent it, I want to send "posxy" from Server al all Clients connected.
I hope that somebody can help me.