How to run client-servet TCP/IP program on two different machines? - c

I googled and stack-overflowed a lot but didn't find any solution. I have a simple echo client-server program in which client sends a word and the server echoes it.
This is my server.c file:
#define PORT 4444
#define MAX_CONNESSIONI 100
int main ()
{
int serverSocket, bindStatus;
struct sockaddr_in serverAddress;
int clientSocket;
struct sockaddr_in newAddress;
char buffer[1024];
pid_t child;
socklen_t addrSize;
ssize_t nread;
// Creazione della socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
perror("[-]Errore durante la creazione della socket\n");
exit(-1);
}
printf("[+]Echo-Server socket has been created\n");
memset(&serverAddress, '\0', sizeof(serverAddress));
// Riempimento dei campi della struct
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
// Binding della socket all'indirizzo specificato. Associa alla socket un indirizzo in modo da poter essere contattata dai client
if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
perror("[-]Errore durante il binding\n");
exit(1);
}
printf("[+]Bind to port %d\n", PORT);
// Imposta la socket all'ascolto. I parametri sono il descrittore della socket e la massima lunghezza della coda di connessioni entranti
if (listen(serverSocket, MAX_CONNESSIONI) != -1) {
printf("Listening . . .\n\n");
}
else {
perror("[-]Error during listening\n");
exit(1);
}
while (1) {
// Accettazione della connessione
clientSocket = accept(serverSocket, (struct sockaddr*)&newAddress, &addrSize);
if (clientSocket == -1) {
exit(-1);
}
printf("%s:%d joined\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port));
child = fork();
if (child == 0) {
close(serverSocket);
while (1) {
// Ricezione del messaggio
if ( (nread=recv(clientSocket, buffer, sizeof buffer - 1, 0)) <= 0) {
perror("[-]Error in receiving data from server\n");
}
else {
buffer[nread] = '\0';
}
if (strcmp(buffer, ":exit") == 0) {
printf("%s:%d left\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port));
break;
}
else {
printf("%s:%d wrote: %s\n", inet_ntoa(newAddress.sin_addr), ntohs(newAddress.sin_port), buffer);
// Invio del messaggio
send(clientSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(clientSocket);
return 0;
}
you can compile it using
gcc -o server.out server.c
and execute it using
./server.out
and this is my client.c file:
#define PORT 4444
int main ()
{
int clientSocket;
struct sockaddr_in serverAddress;
char buffer[1024];
ssize_t nread;
// Creazione della socket
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
perror("[-]Errore durante la creazione della socket\n");
exit(-1);
}
printf("[+]Client socket has been created\n");
memset(&serverAddress, '\0', sizeof(serverAddress));
// Riempimento dei campi della struct
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
// Connessione
if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
perror("Errore con la connessione\n");
exit(-1);
}
printf("[+]Connected to Server\n");
printf("[+]Use single-word and :exit to logout\n");
while (1) {
printf("> ");
//fgets(buffer, 1024, stdin); Per ottenere una stringa con gli spazi
fflush(stdin);
scanf("%s", buffer);
// Invio dei dati al server
if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {
perror("Errore con l'invio");
exit(1);
}
// Per uscire dalla connessione
if(strcmp(buffer, ":exit") == 0) {
close(clientSocket);
printf("[-]Disconnected from Server\n");
exit(0);
}
// Riceve i dati dal server
if ( (nread=recv(clientSocket, buffer, sizeof buffer - 1, 0)) <= 0) {
perror("[-]Error in receiving data from server\n");
}
else {
buffer[nread] = '\0';
printf("Server received: %s\n", buffer);
}
}
close(clientSocket);
return 0;
}
you can compile it using gcc -o client.out client.c
and execute it using ./client.out
This works fine.
How can I edit so that I can execute the server on two different computers?

Change INADDR_ANY to your server IP address.
serverAddress.sin_addr.s_addr = inet_addr("192.168.1.20");

Related

Bad File Descriptor error when writing on a socket Linux

I'm studying sockets and client server communication with select. My problem is that at line 261 i get the Bad File Descriptor error and I have no idea why. The message on line 233 arrives to the client, in the one after (line 252) the client instead of receiving the size in bytes receives 0, and in the write after (line 261) I get the error. I'm really confused.
This is the SERVER
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define DIM_BUFF 100
#define max 10
#define mass(a, b) ((a) > (b) ? (a) : (b))
/********************************************************/
void gestore(int signo) {
int stato;
printf("esecuzione gestore di SIGCHLD\n");
wait(&stato);
}
/********************************************************/
//STRUTTURA DATI
typedef struct{
char Targa[max];
int Patente;
char Tipo[max];
char Folder[max];
}Prenotazione;
//REQUEST DATAGRAM
typedef struct{
char Targa[max];
int newPatente[max];
}Request;
int main(int argc, char **argv) {
//inizializziamo struttura
Prenotazione pren[3];
//dati mock
strcpy(pren[0].Targa,"ciao1");
pren[0].Patente=1234;
strcpy(pren[0].Tipo,"tipo1");
strcpy(pren[0].Folder,"prova1");
strcpy(pren[1].Targa,"ciao2");
pren[1].Patente=1234;
strcpy(pren[1].Tipo,"tipo2");
strcpy(pren[1].Folder,"prova2");
strcpy(pren[2].Targa,"ciao3");
pren[2].Patente=1234;
strcpy(pren[2].Tipo,"tipo3");
strcpy(pren[2].Folder,"prova3");
printf("struttura dati inizializzata!!\n");
int listenfd, connfd, udpfd, nready, maxfdp1;
const int on = 1;
FILE* fd_file;
char zero = '\0' ,Targa[max],fileName[20],path[128];
int buff[DIM_BUFF];
fd_set rset;
int len, nread, nwrite, num, port,count=0;
long size;
struct sockaddr_in cliaddr, servaddr;
Request *req = (Request *)malloc(sizeof(Request));
DIR *dir1;
struct dirent *dd1;
/* CONTROLLO ARGOMENTI ---------------------------------- */
if (argc != 2) {
printf("Error: %s port\n", argv[0]);
exit(1);
}
nread = 0;
while (argv[1][nread] != '\0') {
if ((argv[1][nread] < '0') || (argv[1][nread] > '9')) {
printf("porta non intero\n");
exit(2);
}
nread++;
}
port = atoi(argv[1]);
if (port < 1024 || port > 65535) {
printf("Porta scorretta...");
exit(2);
}
/* INIZIALIZZAZIONE INDIRIZZO SERVER ----------------------------------------- */
memset((char *)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(port);
printf("Server avviato\n");
/* CREAZIONE SOCKET TCP ------------------------------------------------------ */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd < 0) {
perror("apertura socket TCP ");
exit(1);
}
printf("Creata la socket TCP d'ascolto, fd=%d\n", listenfd);
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
perror("set opzioni socket TCP");
exit(2);
}
printf("Set opzioni socket TCP ok\n");
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind socket TCP");
exit(3);
}
printf("Bind socket TCP ok\n");
if (listen(listenfd, 5) < 0) {
perror("listen");
exit(4);
}
printf("Listen ok\n");
/* CREAZIONE SOCKET UDP ------------------------------------------------ */
udpfd = socket(AF_INET, SOCK_DGRAM, 0);
if (udpfd < 0) {
perror("apertura socket UDP");
exit(5);
}
printf("Creata la socket UDP, fd=%d\n", udpfd);
if (setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
perror("set opzioni socket UDP");
exit(6);
}
printf("Set opzioni socket UDP ok\n");
if (bind(udpfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind socket UDP");
exit(7);
}
printf("Bind socket UDP ok\n");
/* AGGANCIO GESTORE PER EVITARE FIGLI ZOMBIE -------------------------------- */
signal(SIGCHLD, gestore);
/* PULIZIA E SETTAGGIO MASCHERA DEI FILE DESCRIPTOR ------------------------- */
FD_ZERO(&rset);
maxfdp1 = mass(listenfd, udpfd) + 1;
/* CICLO DI RICEZIONE EVENTI DALLA SELECT ----------------------------------- */
for (;;) {
FD_SET(listenfd, &rset);
FD_SET(udpfd, &rset);
if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
if (errno == EINTR)
continue;
else {
perror("select");
exit(8);
}
}
//GESTIONE RICHIESTE CAMBIO NUMERO PATENTE--------------------
if (FD_ISSET(udpfd, &rset)) {
int result=-1;
printf("Server: ricevuta richiesta di cambio numero patente\n");
len = sizeof(struct sockaddr_in);
if (recvfrom(udpfd, req, sizeof(Request), 0, (struct sockaddr *)&cliaddr, &len) <
0) {
perror("recvfrom");
continue;
}
printf("targa: %s \n", req->Targa);
printf("nuovo numero patente: %s \n", req->newPatente);
for(int i=0;i<3 && result==-1;i++){
if(strcmp(req->Targa,pren[i].Targa)==0){
pren[i].Patente=*req->newPatente;
result=0;
}
}
printf("cambio numero patente effettuato!, invio risposta... \n");
if (sendto(udpfd, &result, sizeof(result), 0, (struct sockaddr *)&cliaddr, len) < 0) {
perror("sendto");
continue;
}
}//IF UDP
//GESTIONE RICHIESTE SCARICAMENTO IMMAGINI
if (FD_ISSET(listenfd, &rset)) {
printf("Ricevuta richiesta di get di un file\n");
len = sizeof(struct sockaddr_in);
if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len)) < 0) {
if (errno == EINTR)
continue;
else {
perror("accept");
exit(9);
}
}
if (fork() == 0) { /* processo figlio che serve la richiesta di operazione */
close(listenfd);
printf("Dentro il figlio, pid=%i\n", getpid());
char Fold[max];
int trovato=-1;
while ((nread = read(connfd, &Targa, sizeof(Targa))) > 0) {
printf("Server (figlio): targa richiesta: %s\n", Targa);
for(int i=0;i<3;i++){
if(strcmp(Targa,pren[i].Targa)==0){
strcpy(Fold,pren[i].Folder);
trovato=i;
}
}
if(trovato>=0){
dir1 = opendir(Fold);
while ((dd1 = readdir(dir1)) != NULL) {
if (strcmp(dd1->d_name, ".") != 0 && strcmp(dd1->d_name, "..") != 0) {
strcpy(fileName, dd1->d_name);
if (write(connfd, fileName,(strlen(fileName) + 1)) < 0) {
perror("Errore nell'invio del nome file\n");
continue;
}
path[0] = '\0'; //path reset
sprintf(path, "%s/%s", pren[trovato].Folder, dd1->d_name);
fd_file = fopen(path, "rb");
if (fd_file < 0) {
printf("ERRORE Apertura FILE\n");
}
fseek(fd_file, 0, SEEK_END);
size=ftell(fd_file);
fseek(fd_file, 0, SEEK_SET);
printf("le dimensioni sono: %ld" ,size);
//invio la dimensione
if (write(connfd, &size,sizeof(long))< 0) {
perror("Errore nell'invio della dimensione file\n");
exit(0);
}
/* lettura dal file (a blocchi) e scrittura sulla socket */
printf("Leggo e invio il file richiesto\n");
while (count<size) {
nread = fread(buff, sizeof(int), sizeof(buff),fd_file);
if (nwrite = write(connfd, buff, sizeof(buff)) < 0) {
perror("write");
break;
}
bzero(buff, sizeof(buff));
count=count+nread;
}
printf("Terminato invio file\n");
fclose(fd_file);
}
}//while DD1
strcpy(fileName,"fine");
if (write(connfd, fileName,(strlen(fileName) + 1)) < 0) {
perror("Errore nell'invio del nome file\n");
continue;
}
printf("Terminato invio di tutti i file\n");
closedir(dir1);
}//if trovato
else{
strcpy(fileName,"errore");
if (write(connfd, fileName,(strlen(fileName) + 1)) < 0) {
perror("Errore nell'invio del nome file\n");
continue;
}
}
}//while richieste
printf("Figlio TCP terminato, libero risorse e chiudo. \n");
close(connfd);
exit(0);
}//FORK
sleep(1);
close(connfd); //padre chiude la socket(non di ascolto)
}//IF TCP
}//for SELECT
}//main
this is the CLIENT
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define DIM_BUFF 100
#define LENGTH_FILE_NAME 20
int main(int argc, char *argv[]) {
int sd, nread, port,count=0;
char nome_file[LENGTH_FILE_NAME],Targa[10];
struct hostent *host;
struct sockaddr_in servaddr;
int c;
long size;
/* CONTROLLO ARGOMENTI ---------------------------------- */
if (argc != 3) {
printf("Error:%s serverAddress serverPort\n", argv[0]);
exit(1);
}
printf("Client avviato\n");
/* PREPARAZIONE INDIRIZZO SERVER ----------------------------- */
memset((char *)&servaddr, 0, sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
host = gethostbyname(argv[1]);
if (host == NULL) {
printf("%s not found in /etc/hosts\n", argv[1]);
exit(2);
}
nread = 0;
while (argv[2][nread] != '\0') {
if ((argv[2][nread] < '0') || (argv[2][nread] > '9')) {
printf("Secondo argomento non intero\n");
exit(2);
}
nread++;
}
port = atoi(argv[2]);
if (port < 1024 || port > 65535) {
printf("Porta scorretta...");
exit(2);
}
servaddr.sin_addr.s_addr = ((struct in_addr *)(host->h_addr))->s_addr;
servaddr.sin_port = htons(port);
/* CREAZIONE E CONNESSIONE SOCKET (BIND IMPLICITA) ----------------- */
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) {
perror("apertura socket ");
exit(3);
}
printf("Creata la socket sd=%d\n", sd);
if (connect(sd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) < 0) {
perror("Errore in connect");
exit(4);
}
printf("Connect ok\n");
//inizio ciclo richieste
printf("numero della targa o EOF: \n");
while (gets(Targa)) {
if (write(sd, Targa, (strlen(Targa) + 1)) < 0) {
perror("write");
continue;
}
printf("Richiesta della targa %s inviata... \n", Targa);
//ricezione nome file ogni volta
if (read(sd, &nome_file, sizeof(nome_file)) < 0) {
perror("read");
break;
}
while(strcmp(nome_file,"fine")!=0 ){
FILE* f;
printf("il nome del file: %s \n" ,nome_file);
if (read(sd, &size, sizeof(long)) < 0) {
perror("read");
break;
}
if(size==0){
printf("size 0");
exit(1);
}
printf("la size e': %ld" ,size);
f=fopen(nome_file,"wb");
while (count<size){
nread = read(sd, &c, 1);
fwrite(&c,sizeof(int),1,f);
count=count+nread;
}
fclose(f);
printf("immagine ricevuta\n");
if (read(sd, &nome_file, sizeof(nome_file)) < 0) {
perror("read");
break;
}
}
if(strcmp(nome_file,"fine")==0){
printf("tutte le immaigini ricevute\n");
printf("numero della targa o EOF: \n");
}
else{
printf("ERRORE PROTOCOLLO\n");
shutdown(sd, 0);
shutdown(sd, 1);
close(sd);
exit(0);
}
}//whilw
printf("\nClient: termino...\n");
shutdown(sd, 0);
shutdown(sd, 1);
close(sd);
exit(0);
}//main
I've literally tried everything but it doesn't seem to work.
Thanks for your time and sorry form my bad english.

(Socket operation on non socket) error while trying to receive data on a TCP server

What I want to do is send a message (which I type on the terminal) from the client to the server.
I'm getting this error on the server when I try to call the recv() function. As you can see, the client doesn't show errors.
This is the code I've written for the server side:
#define BUFFERLEN 1024
int main(int argc, char **argv)
{
char name[BUFFERLEN];
int sockfd_serv, sockfd_cli, port;
struct sockaddr_in server_addr, client_addr;
sockfd_serv = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd_serv == -1)
{
perror("Error abriendo el socket");
exit(1);
}
bzero((char *)&server_addr, sizeof(server_addr));
port = atoi(argv[1]);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
//Asignamos un puerto al socket
if (bind(sockfd_serv, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
{
perror("Error al asociar el puerto a la conexión");
close(sockfd_serv);
return 1;
}
//Ponemos el servidor a escuchar
listen(sockfd_serv, 5);
printf("Escuchando en el puerto %d\n\n", ntohs(server_addr.sin_port));
while (1)
{
int long_cli = sizeof(client_addr);
//Aceptamos la conexión de un cliente
if (accept(sockfd_serv, (struct sockaddr *)&client_addr, &long_cli) == -1)
{
perror("Error al aceptar conexión");
close(sockfd_serv);
return 1;
}
printf("Conectado con %s:%d\n", inet_ntoa(client_addr.sin_addr), htons(client_addr.sin_port));
int nombre = recv(sockfd_cli, &name, BUFFERLEN, 0);
if (nombre == -1)
{
perror("Name error");
return 1;
}
printf("%s", name);
}
return 0;
}
I'm confused because I'm already checking that the socket is created properly. What does "non-socket" refers to?
You never initialize sockfd_cli. Odds are, it's zero, and that's your standard input terminal and not a socket. You need to store the return value from accept in sockfd_cli.

C Socket: read finish on close in server

I have a simply program with server and client that comunicate with AF_STREAM socket.
Client will can send multiple request to server, and the server response with a string but I don't know the lenght. The client stops in reading when read return 0 and restarts after the server stops the comunication. I don't understand why.
//SEVER
int main(void){
int idSockServer, idSockClient, clientLen;
struct sockaddr_in indirizzoClient, indirizzoServer;
unsigned short richiesta = 0;
char nomeFile[L_STRING], buffer[L_BUFFER];
printf("Inizializzaione del server\n");
idSockServer = socket(AF_INET, SOCK_STREAM, 0);
if(idSockServer == -1){
fprintf(stderr, "Errore socket\n");
exit(EXIT_FAILURE);
}
indirizzoServer.sin_addr.s_addr = htonl(INADDR_ANY);
indirizzoServer.sin_port = htons(5566);
indirizzoServer.sin_family = AF_INET;
if(bind(idSockServer, (struct sockaddr *) &indirizzoServer, sizeof(indirizzoServer))){
fprintf(stderr, "Errore bind\n");
exit(EXIT_FAILURE);
}
if(listen(idSockServer, 5) == -1){
fprintf(stderr, "Errore listen\n");
exit(EXIT_FAILURE);
}
while(1){
printf("[SERVER] Pronto!\n");
clientLen = sizeof(indirizzoClient);
idSockClient = accept(idSockServer, (struct sockaddr *) &indirizzoClient, &clientLen);
if(idSockClient == -1){
printf("[SERVER] Errore alla connessione\n");
continue;
}
read(idSockClient, &richiesta, L_BUFFER);
switch(richiesta){
case 1:
printf("[SERVER] Richiesta 1 accetata, invio risposta\n");
//this simulates the variable lenght string
strcpy(buffer, "un file\n");
write(idSockClient, buffer, L_BUFFER);
break;
}
sleep(6);
close(idSockClient);
}
}
Here the client
//CLIENT
int main(void) {
int sockIdClient, clientLen, file, len;
char buffer[L_BUFFER], nomeFile[L_STRING];
struct sockaddr_in indirizzoClient;
unsigned short scelta, risposta = 0;
sockIdClient = socket(AF_INET, SOCK_STREAM, 0);
if (sockIdClient == -1) {
perror("Errore creazione socket");
exit(EXIT_FAILURE);
}//fine if creazione socket
indirizzoClient.sin_addr.s_addr = htonl(INADDR_ANY);
indirizzoClient.sin_family = AF_INET;
indirizzoClient.sin_port = htons(5566);
if (connect(sockIdClient, (struct sockaddr *) &indirizzoClient, sizeof (indirizzoClient)) == -1) {
perror("Errore connessione al server");
exit(EXIT_FAILURE);
}//fine connect
do {
printf("1) File disponibili\n");
printf("2) Scarica file\n");
printf("0) Esci\n");
printf("Scelta --> ");
scanf("%hu", &scelta);
switch (scelta) {
case 1:
write(sockIdClient, &scelta, sizeof (unsigned short));
len = read(sockIdClient, buffer, L_BUFFER);
while (len > 0) {
printf("%s", buffer);
printf("%d\n", len);
len = read(sockIdClient, buffer, len);
}
break;
case 2:
//This part of code is not managed by Server yet
write(sockIdClient, &scelta, sizeof (unsigned short));
read(sockIdClient, &risposta, sizeof (int));
if (risposta) {
printf("Nome file: ");
leggiStringa(nomeFile, L_STRING);
write(file = sockIdClient, nomeFile, L_STRING);
if (open(nomeFile, O_WRONLY | O_CREAT, "0666") == -1) {
perror("Errore apertura del file");
close(sockIdClient);
exit(EXIT_FAILURE);
}//fine open
len = read(sockIdClient, buffer, L_BUFFER);
while (len > 0) {
write(file, buffer, L_BUFFER);
printf("leggo..\n");
len = read(sockIdClient, buffer, len);
}
close(file);
} else printf("Il server non ha accetato la richiesta\n");
break;
default:
printf("Scelta non valida");
}
} while (scelta != 0);
close(sockIdClient);
}

C - app Socket , not execute printf() before read() in do-while

when i run server and client , server "accept()" the client.
[printf 1] printf (CONNECTION ACCEPTED) and after not run second [printf 2] printf(wait for login client). server run this line only after the client write in socket [login e password] why??
SERVER
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("\nCONNECTION ACCEPTED");
do{
printf("\nWait login from client"); /*<----why this printf not run??*/
bzero(buffer,256);
d = read(newsockfd,buffer,255);
if (d < 0)
error("ERROR reading from socket");
bzero(stringa,30);
strcat(stringa,buffer);
user = strtok(stringa,meno);
password = strtok(NULL,meno);
printf("\nUSER-> %s PASSWORD -> %s\n",user,password);
bzero(risposta,10);
strcat(risposta,checkByUserPass(user,password));
if(strcmp(risposta,"OK")==0)
{
printf("\n--------------TROVATO------------------risposta = %s---\n",risposta);
d = write(newsockfd,"OK",18);
}
else
{
printf("\n--------------NON TROVATO IN ATTESA DI LOGIN VALIDO--------------risposta = %s---\n",risposta);
d = write(newsockfd,"KO",18);
}
}while(strcmp(risposta,"OK")!=0);
CLIENT
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc,char *argv[])
{
char u[20];
char p[10];
char meno[2]="-";
char input[10];
char servizio[10];
int sockfd,portno,n,newsockfd;
struct sockaddr_in serv_addr; //struct sockaddr
struct hostent *server; //hostent è una struttura definita su netdb.h e conterrà le
//informazioni sull'host, attraverso "struct hostent *gethostbyname(char *name);"
char buffer[256];
if(argc<3) //se ci sono meno di 3 argomenti fallisce
{
fprintf(stderr,"usage %s hostname port\n",argv[0]);
exit(0);
}
portno=atoi(argv[2]); //il terzo argomento è il numero di porta
sockfd=socket(AF_INET,SOCK_STREAM,0); //apriamo connessione di tipo socket socketfd descrittore
if(sockfd<0)
{
error("error opening socket");
}
server=gethostbyname(argv[1]); //che prende un nome come attributo e restituisce una puntatore a una struttura
//di tipo hostent contenente le informazioni dell'host
if(server==NULL)
{
fprintf(stderr,"error,no such host\n");
exit(0);
}
bzero((char*)&serv_addr,sizeof(serv_addr)); //azzero il buffer server_addr
serv_addr.sin_family=AF_INET; //compilo i campi
bcopy((char*)server->h_addr,(char*)&serv_addr.sin_addr.s_addr,server->h_length); //uso void bcopy(char *s1,char *s2,int lenght) perchè server->h_addr è una stringa
serv_addr.sin_port=htons(portno); //compilo campi struttura server_addr
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) //fase connect() prende 3 parametri : descrittore , indirizzo di memoria puntatore struct sockaddr,
//dimensione indirizzo
{
error("error connecting");
}
bzero(buffer,256); //azzero il buffer
/*----------PRENDERE USER E PASSWORD----------------------------*/
printf("\nCONNESSIONE AVVENUTA COL SERVER.");
do{
printf("\nINSERIRE DATI PER IL LOGIN.");
sleep(1);
printf("\n\nEnter the user to insert : ");
fgets(u,100,stdin);
if (u[strlen(u) - 1] == '\n') //rimuove lo /n generato dalla fgets
{
u[strlen(u) - 1] = '\0';
}
printf("\n\nEnter the passw to insert : ");
scanf("%s",p);
strcat(u,meno);
strcat(u,p);
bzero(buffer,256);
strcat(buffer,u);
printf("#debug-Messaggio da mandare -> %s", buffer);
sleep(1);
//bzero(u,20);
n=write(sockfd,buffer,strlen(buffer));
if(n<0)
{
error("error writing to socket");
}
bzero(buffer,256);
n=read(sockfd,buffer,255);
if(n<0)
{
error("error reading rom socket");
}
else
{
printf("server: %s",buffer);
//fputs(buffer, stdout);
bzero(servizio,10);
strcat(servizio,buffer);
printf("\nservizio = ---%s---",servizio);
}
if (strcmp(servizio,"OK")==0)
{
printf("\n Login accettato");
getchar();
}
else
{
printf("\n Conto non trovato");
getchar();
}
}while(strcmp(servizio,"OK")!=0);
Add a \n at the end of the text your print else it is not guaranteed that it will be displayed without an explicit fflush. i.e.:
printf("\nWait login from client\n");
Or:
printf("\nWait login from client");
fflush(stdout);

Windows Socket (UDP) - Client TIMEOUT issue

I've a server and a client (code posted bellow).
Im testing the setsockopt function with the SO_RCVTIMEO timeout option in the client program, and it seems to be compiling fine.
The procedure is: server binds to socket for reading - client sends a message to it - server shows message and resends it to whichever client sent it - and finally, client shows message recieved from server
So, to check if the timeout actually fails after X amount of miliseconds (timeout is only used when the client is waiting for the message to be sent back from the server), i inserted a Sleep(miliseconds) function in the server just before it resends the message to the client, so as to balance this delay between the client and the server.
So, when testing with Sleep(0) and timeout at 0 aswell, everything works perfectly synchronized, but if i lift the values to, say, 10 ms on both ends, the result should be the same as with 0, but actually, everything works as planned except when the client awaits for the server's response, it timeout's, eventhough the delay on both ends is exactly the same.
As a last example: if the Sleep on the server is 10ms, and the timeout on the client is 11, or even 15 to leave some more room, what happens is, server recieves message, waits 10ms, resends it, the client that was suposed to wait another 5ms to complete the 15ms, actually timeout's. Even worse, the server after completeting it's whole process resumes it's initial awaiting-response loop, somehow gives me an error on the recvfrom.
Excuse the huge text but it'd be really hard to summarize all of this without leaving some crutial details out.
Client.c (ignore the broadcast, it's not being used)
#include <winsock.h>
#include <stdio.h>
#define SERV_HOST_ADDR "127.0.0.1"
#define SERV_UDP_PORT 6000
#define PORT_MAX 7000
#define PORT_MIN 1000
#define NUM_IT 10
#define BUFFERSIZE 4096
void Abort(char *msg);
/*________________________________ main _______________________________________
*/
int main(int argc, char *argv[])
{
SOCKET sockfd;
int msg_len, iResult, nbytes, addrlength, local_port;
struct sockaddr_in serv_addr, local;
char buffer[BUFFERSIZE];
WSADATA wsaData;
//broadcast
int broadcast, broadcast_loop;
//timeout
DWORD timeout;// = TIMEOUT;
/*========================= TESTA A SINTAXE =========================*/
if (argc != 9){
fprintf(stderr, "(%d argumentos) Sintaxe: %s -msg \"msg\" -ip ip -port port -timeout microsegundos\n (ordem arbitraria)\n", argc, argv[0]);
exit(EXIT_FAILURE);
}
//tratar os argumentos//
int pos_msg, pos_port, pos_ip, pos_timeout, i;
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-msg") == 0)
pos_msg = i + 1;
if (strcmp(argv[i], "-ip") == 0)
pos_ip = i + 1;
if (strcmp(argv[i], "-port") == 0)
pos_port = i + 1;
if (strcmp(argv[i], "-timeout") == 0)
pos_timeout = i + 1;
}
timeout = atol((char*)(LPCTSTR)argv[pos_timeout]); //converter timeout STRING para DWORD
if (strcmp(argv[pos_ip], "255.255.255.255") == 0)
{
broadcast_loop = 1;
broadcast = 1;
}
else
{
broadcast_loop = 0;
broadcast = 0;
}
/*=============== INICIA OS WINSOCKS ==============*/
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
getchar();
exit(1);
}
/*=============== CRIA SOCKET PARA ENVIO/RECEPCAO DE DATAGRAMAS ==============*/
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET)
Abort("Impossibilidade de criar socket");
/*================ CONFIGURA O SOCKET PARA TIMEOUT DE RECEPCAO ==============*/
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
//this call is what allows broadcast packets to be sent:
if (broadcast_loop == 1)
{
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof broadcast) == -1)
{
perror("setsockopt (SO_BROADCAST)");
exit(1);
}
}
/*================= PREENCHE ENDERECO DO SERVIDOR ====================*/
memset((char*)&serv_addr, 0, sizeof(serv_addr)); /*Coloca a zero todos os bytes*/
serv_addr.sin_family = AF_INET; /*Address Family: Internet*/
//serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR); /*IP no formato "dotted decimal" => 32 bits*/
serv_addr.sin_addr.s_addr = inet_addr(argv[pos_ip]);
//serv_addr.sin_port = htons(SERV_UDP_PORT); /*Host TO Netowork Short*/
serv_addr.sin_port = htons(atoi(argv[pos_port]));
/*====================== ENVIA MENSAGEM AO SERVIDOR ==================*/
msg_len = strlen(argv[pos_msg]);
if (broadcast_loop == 1)
{
//loop sem esperar pelo reenvio
for (int i = 0; i < NUM_IT; i++)
{
for (int pt = PORT_MIN; pt <= PORT_MAX; pt++)
{
serv_addr.sin_port = htons(pt);
if (sendto(sockfd, argv[pos_msg], msg_len, 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
Abort("SO nao conseguiu aceitar o datagram");
printf(" -Enviada mensagem %d (port: %d)\n", i, pt);
//ir buscar a porta gerada automaticamente pare este socket e mostrá-la
addrlength = sizeof(local);
if (getsockname(sockfd, (struct sockaddr *)&local, &addrlength) == 0 && local.sin_family == AF_INET && addrlength == sizeof(local))
{
local_port = ntohs(local.sin_port);
}
printf("<CLI1>Mensagem enviada (port: %d) ... aguardando pelo seu reenvio.\n", local_port);
}
//////// ESPERAR QUE MESMA MENSAGEM SEJA REENVIADA PELO SERVIDOR //////
////nbytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL);
////memset((char*)&serv_addr, 0, sizeof(serv_addr));
//addrlength = sizeof(serv_addr);
//nbytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&serv_addr, &addrlength);
//if (nbytes == SOCKET_ERROR)
// Abort("Erro na recepcao da mensagem");
//buffer[nbytes] = '\0'; /*Termina a cadeia de caracteres recebidos com '\0'*/
//printf("\n<CLI1>Mensagem recebida {%s}\n", buffer);
//if (strcmp(inet_ntoa(serv_addr.sin_addr), SERV_HOST_ADDR) == 0 && ntohs(serv_addr.sin_port) == SERV_UDP_PORT)
// printf(" -Mensagem enviada pelo servidor -> %s:%d\n", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
//else
// printf(" -Mensagem NAO enviada pelo servidor -> %s:%d\n", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
}
}
else
{
if (sendto(sockfd, argv[pos_msg], msg_len, 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
Abort("SO nao conseguiu aceitar o datagram");
//ir buscar a porta gerada automaticamente pare este socket e mostrá-la
addrlength = sizeof(local);
if (getsockname(sockfd, (struct sockaddr *)&local, &addrlength) == 0 && local.sin_family == AF_INET && addrlength == sizeof(local))
{
local_port = ntohs(local.sin_port);
}
printf("<CLI1>Mensagem enviada (port: %d) ... aguardando pelo seu reenvio (timeout).\n", local_port);
////// ESPERAR QUE MESMA MENSAGEM SEJA REENVIADA PELO SERVIDOR //////
//nbytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL);
//memset((char*)&serv_addr, 0, sizeof(serv_addr));
addrlength = sizeof(serv_addr);
nbytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&serv_addr, &addrlength);
if (nbytes == SOCKET_ERROR)
if (WSAGetLastError() != WSAETIMEDOUT)
Abort("Erro na recepcao da mensagem");
else
Abort("Timeout de recepcao");
buffer[nbytes] = '\0'; /*Termina a cadeia de caracteres recebidos com '\0'*/
printf("\n<CLI1>Mensagem recebida {%s}\n", buffer);
if (strcmp(inet_ntoa(serv_addr.sin_addr), SERV_HOST_ADDR) == 0 && ntohs(serv_addr.sin_port) == SERV_UDP_PORT)
printf(" -Mensagem enviada pelo servidor -> %s:%d\n", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
else
printf(" -Mensagem NAO enviada pelo servidor -> %s:%d\n", inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
}
/*========================= FECHA O SOCKET ===========================*/
closesocket(sockfd);
printf("\n");
system("Pause");
exit(EXIT_SUCCESS);
}
/*________________________________ Abort________________________________________
Mostra uma mensagem de erro e o código associado ao ultimo erro com Winsocks.
Termina a aplicacao com "exit status" a 1 (constante EXIT_FAILURE)
________________________________________________________________________________*/
void Abort(char *msg)
{
fprintf(stderr, "<CLI1>Erro fatal: <%s> (%d)\n", msg, WSAGetLastError());
exit(EXIT_FAILURE);
}
and Server.c
#include <stdio.h>
#include <winsock.h>
#include <Windows.h> //Sleep()
#define SERV_UDP_PORT 6000
#define BUFFERSIZE 4096
void Abort(char *msg);
/*________________________________ main ________________________________________
*/
int main(int argc, char *argv[])
{
SOCKET sockfd;
int iResult, nbytes, msg_len, len;
struct sockaddr_in serv_addr, cli_addr;
char buffer[BUFFERSIZE];
WSADATA wsaData;
/*========================= TESTA A SINTAXE =========================*/
if (argc != 5){
fprintf(stderr, "(%d argumentos) Sintaxe: %s -port port -delay delay\n", argc, argv[0]);
exit(EXIT_FAILURE);
}
//tratar os argumentos//
int pos_port, pos_delay, i;
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-port") == 0)
pos_port = i + 1;
if (strcmp(argv[i], "-delay") == 0)
pos_delay = i + 1;
}
/*=============== INICIA OS WINSOCKS ==============*/
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
getchar();
exit(1);
}
/*============ CRIA O SOCKET PARA RECEPCAO/ENVIO DE DATAGRAMAS UDP ============*/
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
Abort("Impossibilidade de abrir socket");
/*=============== ASSOCIA O SOCKET AO ENDERECO DE ESCUTA ===============*/
/*Define que pretende receber datagramas vindos de qualquer interface de
rede, no porto pretendido*/
memset((char*)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; /*Address Family: Internet*/
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*Host TO Network Long*/
serv_addr.sin_port = htons(atoi(argv[pos_port])); /*Host TO Network Short*/
/*Associa o socket ao porto pretendido*/
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
Abort("Impossibilidade de registar-se para escuta");
/*================ PASSA A ATENDER CLIENTES INTERACTIVAMENTE =============*/
while (1){
fprintf(stderr, "<SER1>Esperando datagram...\n");
len = sizeof(cli_addr);
//recieve from, tem agora de saber de quem recebeu, para reenviar
nbytes = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&cli_addr, &len);
if (nbytes == SOCKET_ERROR)
Abort("Erro na recepcao de datagrams");
buffer[nbytes] = '\0'; /*Termina a cadeia de caracteres recebidos com '\0'*/
printf("<SER1>Mensagem recebida {%s} de %s:%d\n", buffer, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
////// REENVIAR A MENSAGEM AO CLIENTE //////
msg_len = strlen(buffer);
Sleep(atoi(argv[pos_delay])); //sleep de 'delay' milisegundos
if (sendto(sockfd, buffer, msg_len, 0, (struct sockaddr*)&cli_addr, sizeof(cli_addr)) == SOCKET_ERROR)
Abort("SO nao conseguiu aceitar o datagram");
printf("<SER1>Mensagem reenviada.\n\n");
}
system("Pause");
}
/*________________________________ Abort________________________________________
Mostra uma mensagem de erro e o código associado ao ultimo erro com Winsocks.
Termina a aplicacao com "exit status" a 1 (constante EXIT_FAILURE)
________________________________________________________________________________*/
void Abort(char *msg)
{
fprintf(stderr, "<SER1>Erro fatal: <%s> (%d)\n", msg, WSAGetLastError());
printf("\n");
system("Pause");
exit(EXIT_FAILURE);
}
If anyone could make sense out of all this post and provide some helpful answers, i'd greatly appreciate it.

Resources