Related
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.
I am writing a private chat using UDP, but I have some problems while implementing the registration service. When the client writes the ID and password he wants to use, the server checks if the ID already exists(IDs and password are saved in a file), if it doesn't exist yet, the client can start chatting with other users(I still haven't implemented this part), if the ID is already in use I want to tell the user to choose another ID. In this scenario, I send the message "ID already in use" to the client using sendto but the recvfrom sometimes riceives other messages. Precisely the first time the user chooses a wrong ID, he receives the right message, then, if he chooses again an ID already in use, from the message he has received from the server he reads the ID he tried to choose and not the error message.The strangest thing is that at a third wrong attempt, the error message is correct.
Messages and related functions are defined in a file called utils.h
typedef struct Message{
int type; //Message's type: 0->registration; 1->login; 2->message; 3->ack
char* dest;
char* mitt; //source
char msg[1024];
}Message;
//createMsg is used to fill message struct
int createMsg(int type, char* dest, char* mitt, char * msg, struct Message* message){ //char msg[1024]
//printf("Sono in createMsg\n");
memset(message,0,sizeof(*message));
message->type = type;
message->dest = dest;
message->mitt = mitt;
//printf("msg to write: %s\n",msg);
strcpy(message->msg,msg);
//printf("msg written: %s\n",message->msg);
}
//print messages
void printMsg(struct Message* message){
if(strlen(message->msg)!=0) printf("type: %d, dest: %s, mitt:%s, msg: %s\n",message->type,message->dest,message->mitt,message->msg);
printf("dim msg tot: %lu\n",sizeof(*message));
printf("type dim: %lu, dest dim: %lu, mitt dim:%lu, msg dim: %lu, dim tot msg: %lu\n",sizeof(message->type),sizeof(message->dest),sizeof(message->mitt),strlen(message->msg),sizeof(message->msg));
}
//Set message's field to zero
void setToZeroMsg(struct Message* message){
message->type = 0;
message->dest = NULL;
message->mitt = NULL;
int i=0;
for(i=0;i<strlen(message->msg);i++){
message->msg[i]=0;
}
//memset(message->msg,0,strlen(message->msg));
}
This is the server:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h> // htons()
#include <netinet/in.h> // struct sockaddr_in
#include <sys/socket.h>
//#include "utente.h"
#include "utils.h"
#define MAX_CONNECTIONS 5
#define MAX_MESSAGE 1024
int main(){
int sockfd, ret;
char buffer[MAX_MESSAGE];
size_t buf_len = sizeof(buffer);
struct sockaddr_in server_addr, client_addr;
int serv_addr_len = sizeof(server_addr);
int client_addr_len = sizeof(client_addr);
//socket file descriptor
sockfd = socket(AF_INET, SOCK_DGRAM,0);
if(sockfd < 0){
perror("Errore nel creare la socket!");
exit(EXIT_FAILURE);
}
//Setting structure's content to zero
memset(&server_addr,0,serv_addr_len);
memset(&client_addr,0,client_addr_len);
//Server addr
server_addr.sin_family = AF_INET; //IPv4
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(5500);
//Bind
ret = bind(sockfd, (const struct sockaddr *)&server_addr, serv_addr_len);
if(ret < 0){
perror("Errore nella bind!");
exit(EXIT_FAILURE);
}
struct Message* newmsg = (struct Message*)malloc(sizeof(struct Message));
//Start comunication with clients
//int num_clients = 0;
while(1){
setToZeroMsg(newmsg); //Cancel previous messages
printf("waiting for a message from a client...\n");
//Receiving a message
ret = recvfrom(sockfd, newmsg, sizeof(*newmsg), 0, (struct sockaddr*)&client_addr, &client_addr_len);
if(ret == -1){
perror("Errore nella recvfrom!");
}
printMsg(newmsg);
int type = newmsg->type;
if(type == 0){ //Type==0 -> register request
printf("register request\n");
int newID = 0; //if is set to -1 the ID already exist
size_t msg_len=sizeof(newmsg->msg);
FILE* file = fopen("utenti.txt","r+");
if(file==NULL){
perror("Errore nell'apertura del file");
}
char* newuser = strcpy(newser,newmsg->msg);
strtok(newuser,";");
int size_newuser = sizeof(newuser);
while(1){
char* res = fgets(buffer,32,file);
if(res==NULL) break;
//printf("%s",buffer);
char* user = strtok(buffer,";");
//printf("%s\n",user);
int size_user = sizeof(user);
int size = (size_newuser > size_user)? size_newuser : size_user;
if(strncmp(newuser,user,size) == 0){
//printf("This name is already in use!\n");
/*memset(newmsg,0,sizeof(Message));
newmsg->type = 3;
newmsg->dest = NULL;
strcpy(newmsg->msg, "This ID is already taken!\n");
printf("mess: %s",newmsg->msg);*/
//Error message to client
creaMsg(3, NULL, NULL, "This ID is already taken!\n", newmsg); //buffer
printMsg(newmsg);
printf("msg: %s\n",newmsg->msg);
//ret = sendto(sockfd, (struct Message*)newmsg, sizeof(*newmsg), 0, (struct sockaddr*)&client_addr, (socklen_t) client_addr_len);
ret = sendto(sockfd,newmsg->msg,sizeof(newmsg->msg),0,(struct sockaddr*)&client_addr, (socklen_t) client_addr_len );
if(ret == -1){
perror("Errore nella sendto!");
exit(EXIT_FAILURE);
}
newID = -1;
break;
}
}
if(newID != -1){
ret = fprintf(file,newmsg->msg,msg_len);
if(ret == -1){
perror("Errore nella scrittura su file");
}
}
if(fclose(file) == -1) perror("Errore nella chiusura del file");
}
else if(type==1){
}
else if(type==2){
}
//This part is not implemented yet
/*ret = sendto(sockfd, buffer, buf_len,0,(const struct sockaddr*)&client_addr, (socklen_t) client_addr_len);
if(ret == -1){
perror("Errore nella sendto!");
}*/
}
close(sockfd);
return 0;
}
And this is the client file:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h> // htons()
#include <netinet/in.h> // struct sockaddr_in
#include <sys/socket.h>
//#include "utente.h"
#include "utils.h"
#define MAX_MESSAGE 1024
#define quit_command "QUIT"
int main(){
int sockfd, ret;
struct sockaddr_in server_addr;
int serv_addr_len = sizeof(server_addr);
char buffer[MAX_MESSAGE];
size_t buf_len = sizeof(buffer);
size_t msg_len;
int quit_command_len = strlen(quit_command);
//Message struct
struct Message message = {};
setToZeroMsg(&message);
//socket file descriptor
sockfd = socket(AF_INET, SOCK_DGRAM,0);
if(sockfd < 0){
perror("Errore nel creare la socket!");
exit(EXIT_FAILURE);
}
//Structures to zero
memset(&server_addr,0,serv_addr_len);
//Initialize server_addr
server_addr.sin_family = AF_INET; //IPv4
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(5500);
printf("Welcome in Private Chat!\n");
while(1){
char buf_credentials[32];
memset(buf_credentials,0,sizeof(buf_credentials));
memset(buffer,0,sizeof(buffer));
//setToZeroMsg(&message);
printf("If you want to register write 'r', to login type 'l':\n");
if (fgets(buffer, MAX_MESSAGE, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
if(!memcmp(buffer, "l", 1)){
printf("not implemented yet");
break;
}
else if(!memcmp(buffer,"r",1)){
printf("To register choose an ID and a password.\n");
printf("ID:\n");
if (fgets(buffer, 15, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
//printf("%s\n",buffer);
strncpy(buf_credentials,buffer,strlen(buffer)-1);
strcat(buf_credentials,";");
printf("Inserire password:\n");
if (fgets(buffer, 15, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
strcat(buf_credentials,buffer);
printf("utente+pass: %s",buf_credentials);
//Message struct
/*
struct Message message = {
};*/
setToZeroMsg(&message);
strcpy(message.msg, buf_credentials);
//send ID e password to server
ret = sendto(sockfd, (struct Message*)&message, sizeof(message), 0, (struct sockaddr*)&server_addr, (socklen_t) serv_addr_len);
if(ret == -1){
perror("Errore nella sendto!");
continue;
}
setToZeroMsg(&message);
printf("msg: %s\n",message.msg);
//ret = recvfrom(sockfd, (struct Message*)&message, sizeof(message), 0, (struct sockaddr*)&server_addr, (socklen_t*)&serv_addr_len);
ret = recvfrom(sockfd, message.msg, sizeof(message.msg), 0, (struct sockaddr*)&server_addr, (socklen_t*)&serv_addr_len);
printMsg(&message);
printf("msg: %s\n",message.msg);
if(ret == -1){
perror("Errore nella recvfrom!");
}
continue;
}
else{ //User didn't type 'r' or 'l'
printf("Wrong, you have to type 'r' o 'l'\n");
}
memset(buffer,0,MAX_MESSAGE);
}
//Chatting with server
while(1){
memset(buffer,0,MAX_MESSAGE);
printf("Type the message for the server, QUIT to leave the chat:\n");
if (fgets(buffer, MAX_MESSAGE, stdin) != (char*)buffer) {
fprintf(stderr, "Error while reading from stdin, exiting...\n");
exit(EXIT_FAILURE);
}
printf("You wrote: %s\n", buffer);
msg_len=strlen(buffer);
//Send Message
ret = sendto(sockfd, buffer, MAX_MESSAGE, 0, (struct sockaddr*)&server_addr, (socklen_t) serv_addr_len);
if(ret == -1){
perror("Errore nella sendto!");
continue;
}
//Server wrote back
memset(buffer,0,MAX_MESSAGE);
ret = recvfrom(sockfd, buffer, buf_len, 0, (struct sockaddr*)&server_addr, &serv_addr_len);
if(ret == -1){
perror("Errore nella recvfrom!");
}
printf("Message received from server: %s\n",buffer);
//Controlla se il messaggio ricevuto รจ QUIT
if (msg_len == quit_command_len+1 && !memcmp(buffer, quit_command, quit_command_len)) break;
}
printf("Closing connection!\n");
close(sockfd);
return 0;
}
ID and password are stored in the file "utenti.txt", separated by semicolons, in this way:
ID1;password1
ID2;password2
...
I hope I have been clear about my problem, thank you for helping me!
I have to create a multithread TCP/IP server which contains a variable to count the number of clients connected (and those which disconnect) and print the number of clients connected when a client connects to the server.
This is my client.c file:
#define PORT 4444
int main ()
{
int clientSocket;
struct sockaddr_in serverAddress;
char buffer[1024];
ssize_t nread;
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));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
perror("Errore con la connessione\n");
exit(-1);
}
while (1) {
printf("> ");
fflush(stdin);
scanf("%s", buffer);
if (nread != -1)
buffer[nread] = '\0';*/
if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {
perror("Errore con l'invio");
exit(1);
}
if(strcmp(buffer, ":exit") == 0) {
close(clientSocket);
printf("[-]Disconnected from Server\n");
exit(0);
}
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;
}
and this is my server.c file:
#define PORT 4444
#define MAX_CONNESSIONI 100
typedef struct myStruct {
int clientCollegati;
int clientCheSiSonoScollegati;
pthread_mutex_t mutex; // Creazione del mutex per sincronizzare la struttura
} myStruct;
myStruct *test;
myStruct *initStruct();
void *incrementa(void*);
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;
pthread_t tid;
test = initStruct();
if (pthread_create(&tid, NULL, incrementa, NULL) != 0) {
perror("Errore nella creazione del thread t1\n");
exit(1);
}
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
perror("[-]Errore durante la creazione della socket\n");
exit(-1);
}
memset(&serverAddress, '\0', sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
bindStatus = bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
if (bindStatus == -1) {
perror("[-]Errore durante il binding\n");
exit(1);
}
printf("[+]Bind to port %d\n", PORT);
if (listen(serverSocket, MAX_CONNESSIONI) != -1) {
printf("Listening . . .\n\n");
}
else {
perror("[-]Error during listening\n");
exit(1);
}
while (1) {
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));
if (pthread_join(tid, NULL)) { // returns 3
perror("pthread_join error\n");
exit(1);
}
printf("There is/are %d client(s) connected\n", test->clientCollegati);
child = fork();
if (child == 0) {
close(serverSocket);
while (1) {
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);
send(clientSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(clientSocket);
return 0;
}
myStruct *initStruct()
{
struct myStruct *ptr = malloc(sizeof(myStruct));
ptr->clientCollegati = 0;
ptr->clientCheSiSonoScollegati = 0;
pthread_mutex_init(&ptr->mutex, NULL); // inizializzazione dinamica del mutex
return ptr;
}
void *incrementa(void *ptr)
{
pthread_mutex_lock(&test->mutex);
test->clientCollegati++;
pthread_mutex_unlock(&test->mutex);
pthread_exit(0);
}
Unfortunately this seems not to work properly, ans you can see server output and here client1 and here client2 output
Where's the mistake? I suppose that the problem is when tid finish and a second call to that pthread_join is invoked to a non-existent thread (because there is a single thread)
Your code logic is wrong. You are doing a single pthread_create() and then multiple pthread_join(). If you want to increment the values for every connected client you have to do one pthread_create() after every single successful accept(), followed by one pthread_join(). Note: all this must happen before the call to fork().
Where's the mistake? I suppose that the problem is when tid finish and a second call to that pthread_join is invoked to a non-existent thread (because there is a single thread)
That's exactly what happens. In your current program, the first pthread_join() is successful, and any successive call fails with errno 3 (no such process) because the thread doesn't exist anymore. So you already figured this out. Why are you creating one thread but joining it multiple times if you know that's wrong?
The way your program is written (fork after the increment) also means that there really is no reason at all to use threads to do the increment, and you don't even need the mutex, since only one single thread will access the value at any given time. In other words, your server isn't multithreaded at all. If you only want to do this as an experiment that's ok, but it doesn't make much sense.
What you probably want to do (to have a multithreaded server) is to have one thread per client instead of forking each time, with the client code in the thread function (in that case having a mutex makes sense). Beware though that this does not scale well for large numbers of clients (in general, the classical fork() approach is better, in which case you really don't need any thread).
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");
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Code Description
I have a concurrent server using select() that spawns a child for every 2 clients connected and gets their name. Parent reads the name from the client's socket and sends it to the child through a pipe ( every child gets its own pipe to communicate with parent, stored in struct child_fd[], along with file descriptors of its 2 clients) who writes back to client.
Error
On line 297 (I have highlighted it in code like this : ----- !!! LINE 297 !!! ----- )(145 in Minimal Reproductive)in server code when I write back to client I get the bad file descriptor error. I never close any socket in my program, and also, I print that player2_fd (player_fd = 7) before writing and it is correct: I also printed it when the connection is made on line 141 (25 in Minimal reproductive) with accept() and it' also 7.Moreover, even in the moment I send this descriptor from parent to child through pipe it is also 7.
Observation
The only difference between the first client and the second is that the first one's descriptor is given to fork child in the moment of forking( as it duplicates all variables) and the second one is sent through the pipe.
MINIMAL REPRODUCTIVE EXAMPLE SERVER CODE:
int main ()
{
struct {
int player1_fd, player2_fd, pipe[2];
}child_fd[20];
// CODE FOR CONNECTION: listen(), bind()...
/* servim in mod concurent clientii... */
while (1)
{
if (select (nfds+1, &readfds, NULL, NULL, NULL) < 0)
{
perror ("[server] Eroare la select().\n");
return errno;
}
if (FD_ISSET (sd, &readfds)) {
// ----- !!! LINE 25 !!! ------ //
client = accept(sd, (struct sockaddr *) &from, &len);
/* eroare la acceptarea conexiunii de la un client */
if (client < 0) {
perror("[server] Eroare la accept().\n");
continue;
}
if (nfds < client) /* ajusteaza valoarea maximului */
nfds = client;
/* includem in lista de descriptori activi si acest socket */
FD_SET (client, &actfds);
printf("[server] S-a conectat clientul cu descriptorul %d, de la adresa %s.\n", client, conv_addr(from));
fflush(stdout);
clientCounter++;
if (clientCounter % 2 == 1) // if it's a player waiting for opponent
{
child_fd[nrOfChilds].player2_fd = -1; // player2_fd is not known yet
child_fd[nrOfChilds].player1_fd = client; // remember it's fd (need it in match handler child)
if (-1 == pipe(child_fd[nrOfChilds].pipe)) {
perror("Error at creating pipe\n");
return errno;
}
if (-1 == (pid = fork())) {
perror("Error at fork.\n");
return errno;
}
if (pid == 0) { // [child that handles a chess match]
/* child only needs it's own information from the struct so I will create local variables*/
int p[] = {child_fd[nrOfChilds].pipe[0], child_fd[nrOfChilds].pipe[1]},
player1_fd = child_fd[nrOfChilds].player1_fd,
player2_fd = child_fd[nrOfChilds].player2_fd;
int infoFromPipe;
char msgrasp[20]=" ";
printf("pipe: %d %d", p[0],p[1]);
fflush(stdout);
while(1)
{
if (-1 == read(p[0], &infoFromPipe, sizeof(int)))
{
perror("Error at reading from pipe\n");
return errno;
}
printf("--%d--", infoFromPipe);
fflush(stdout);
if (infoFromPipe == 1) { // means there is a fd for player2 coming
if (-1 == read(p[0], &player2_fd, sizeof(int)))
{
perror("Error at reading from pipe\n");
return errno;
}
printf("\np2 fd:%d\n", player2_fd);
fflush(stdout);
}
else
{ // both players connected
int player;
if (-1 == read(p[0], &player, sizeof(int))) // reading the player int
{
perror("Error at reading from pipe\n");
return errno;
}
printf("player:%d\n",player);
fflush(stdout);
if ( player == 1){
// EXACTLY THE SAME AS FOR PLAYER 2
}
}
else{ //player 2
int nameOrMove;
if (-1 == read(p[0], &nameOrMove, sizeof(int))) // reading the name or move int
{
perror("Error at reading from pipe\n");
return errno;
}
printf("nameormove:%d\n",nameOrMove);
fflush(stdout);
if (nameOrMove == 0) { // name
int bytesRead, playerNameLen = 0;
char playerName[20],c;
bzero(playerName,20);
if( -1 == read(p[0], &playerNameLen, sizeof(int)))
{
perror("Error at reading from pipe.\n");
return errno;
}
if( -1 == read(p[0], playerName, playerNameLen))
{
perror("Error at reading from pipe.\n");
return errno;
}
printf("Playername: %s\n", playerName);
fflush(stdout);
//mesaj de raspuns pentru client
bzero(msgrasp,100);
strcat(msgrasp,"Hello ");
strcat(msgrasp,playerName);
printf("[server]Trimitem mesajul inapoi...%s\n",msgrasp);
fflush(stdout);
printf("p2fd: %d\n", player2_fd);
fflush(stdout);
// ----- !!! LINE 145 !!! ----- //
if(-1 == write(player2_fd, msgrasp, sizeof(msgrasp)))
{
perror("Error at writing to player1");
return errno;
}
printf("Player name sent\n");
fflush(stdout);
}
}
}
}
}
nrOfChilds++;
} else { // if it's the second player to be assigned to a waiting player 1
if (pid > 0) {
int x = 1;
if (-1 == write(child_fd[nrOfChilds-1].pipe[1], &x, sizeof(int)))
{
perror("Error at writing in pipe\n");
return errno;
}
if (-1 == write(child_fd[nrOfChilds-1].pipe[1], &client, sizeof(int))) //sending player2 socket descriptor to it's child process handler
{
perror("Error at writing in pipe\n");
return errno;
}
child_fd[nrOfChilds-1].player2_fd = client; //adding it to struct so the parent knows both players associated to each child process
}
}
}
/* vedem daca e pregatit vreun socket client pentru a trimite raspunsul */
if (pid > 0) {
for (fd = 0; fd <= nfds; fd++) /* parcurgem multimea de descriptori */
{
/* este un socket de citire pregatit? */
if (fd != sd && FD_ISSET (fd, &readfds)) {
for(int i = 0; i< nrOfChilds; ++i){ // looking for the child process to whom the client is associated
if ( fd == child_fd[i].player1_fd || fd == child_fd[i].player2_fd){
// READING FROM CLIENT SOCKET, SENDING PLAYER NAME TO CHILD
}
FD_CLR(fd, &actfds);
}
}
}
}
}
/* for */
}
} /* while */
/* main */
Server code:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
/* portul folosit */
#define PORT 2726
extern int errno; /* eroarea returnata de unele apeluri */
/* functie de convertire a adresei IP a clientului in sir de caractere */
char * conv_addr (struct sockaddr_in address)
{
static char str[25];
char port[7];
/* adresa IP a clientului */
strcpy (str, inet_ntoa (address.sin_addr));
/* portul utilizat de client */
bzero (port, 7);
sprintf (port, ":%d", ntohs (address.sin_port));
strcat (str, port);
return (str);
}
/* programul */
void sayHello(int);
int main ()
{
struct sockaddr_in server; /* structurile pentru server si clienti */
struct sockaddr_in from;
fd_set readfds; /* multimea descriptorilor de citire */
fd_set actfds; /* multimea descriptorilor activi */
struct timeval tv; /* structura de timp pentru select() */
int sd, client; /* descriptori de socket */
int optval=1; /* optiune folosita pentru setsockopt()*/
int fd, clientCounter = 0, nrOfChilds = 0, txt_fd; // descriptor folosit pentru
pid_t pid = 1; //parcurgerea listelor de descriptori
int nfds; /* numarul maxim de descriptori */
int len; /* lungimea structurii sockaddr_in */
bool waitingForOpponent;
struct {
int player1_fd, player2_fd, pipe[2];
}child_fd[20];
bzero(child_fd, sizeof(child_fd));
if(-1 == mkfifo("my_fifo", 0600) ) {
if (errno == EEXIST) {
printf("Using already existent fifo: \"my_fifo\" ...\n");
} else {
perror("Error at creating \"my_fifo\" file.\n");
exit(1);
}
}
/* creare socket */
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("[server] Eroare la socket().\n");
return errno;
}
/*setam pentru socket optiunea SO_REUSEADDR */
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,&optval,sizeof(optval));
/* pregatim structurile de date */
bzero (&server, sizeof (server));
/* umplem structura folosita de server */
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl (INADDR_ANY);
server.sin_port = htons (PORT);
/* atasam socketul */
if (bind (sd, (struct sockaddr *) &server, sizeof (struct sockaddr)) == -1)
{
perror ("[server] Eroare la bind().\n");
return errno;
}
/* punem serverul sa asculte daca vin clienti sa se conecteze */
if (listen (sd, 5) == -1)
{
perror ("[server] Eroare la listen().\n");
return errno;
}
/* completam multimea de descriptori de citire */
FD_ZERO (&actfds); /* initial, multimea este vida */
FD_SET (sd, &actfds); /* includem in multime socketul creat */
tv.tv_sec = 1; /* se va astepta un timp de 1 sec. */
tv.tv_usec = 0;
/* valoarea maxima a descriptorilor folositi */
nfds = sd;
printf ("[server] Asteptam la portul %d...\n", PORT);
fflush (stdout);
/* servim in mod concurent clientii... */
while (1)
{
/* ajustam multimea descriptorilor activi (efectiv utilizati) */
bcopy ((char *) &actfds, (char *) &readfds, sizeof (readfds));
/* apelul select() */
if (select (nfds+1, &readfds, NULL, NULL, NULL) < 0)
{
perror ("[server] Eroare la select().\n");
return errno;
}
/* vedem daca e pregatit socketul pentru a-i accepta pe clienti */
if (FD_ISSET (sd, &readfds)) {
/* pregatirea structurii client */
len = sizeof(from);
bzero(&from, sizeof(from));
/* a venit un client, acceptam conexiunea */
// ----- !!! LINE 141 !!! -----
client = accept(sd, (struct sockaddr *) &from, &len);
/* eroare la acceptarea conexiunii de la un client */
if (client < 0) {
perror("[server] Eroare la accept().\n");
continue;
}
if (nfds < client) /* ajusteaza valoarea maximului */
nfds = client;
/* includem in lista de descriptori activi si acest socket */
FD_SET (client, &actfds);
printf("[server] S-a conectat clientul cu descriptorul %d, de la adresa %s.\n", client, conv_addr(from));
fflush(stdout);
clientCounter++;
if (clientCounter % 2 == 1) // if it's a player waiting for opponent
{
child_fd[nrOfChilds].player2_fd = -1; // player2_fd is not known yet
child_fd[nrOfChilds].player1_fd = client; // remember it's fd (need it in match handler child)
if (-1 == pipe(child_fd[nrOfChilds].pipe)) {
perror("Error at creating pipe\n");
return errno;
}
if (-1 == (pid = fork())) {
perror("Error at fork.\n");
return errno;
}
if (pid == 0) { // [child that handles a chess match]
/* child only needs it's own information from the struct so I will create local variables*/
int p[] = {child_fd[nrOfChilds].pipe[0], child_fd[nrOfChilds].pipe[1]},
player1_fd = child_fd[nrOfChilds].player1_fd,
player2_fd = child_fd[nrOfChilds].player2_fd;
int infoFromPipe;
char msgrasp[20]=" ";
printf("pipe: %d %d", p[0],p[1]);
fflush(stdout);
while(1)
{
if (-1 == read(p[0], &infoFromPipe, sizeof(int)))
{
perror("Error at reading from pipe\n");
return errno;
}
printf("--%d--", infoFromPipe);
fflush(stdout);
if (infoFromPipe == 1) { // means there is a fd for player2 coming
if (-1 == read(p[0], &player2_fd, sizeof(int)))
{
perror("Error at reading from pipe\n");
return errno;
}
printf("\np2 fd:%d\n", player2_fd);
fflush(stdout);
}
else
{ // both players connected
int player;
if (-1 == read(p[0], &player, sizeof(int))) // reading the player int
{
perror("Error at reading from pipe\n");
return errno;
}
printf("player:%d\n",player);
fflush(stdout);
if ( player == 1){
int nameOrMove;
if (-1 == read(p[0], &nameOrMove, sizeof(int))) // reading the name or move int
{
perror("Error at reading from pipe\n");
return errno;
}
printf("nameormove:%d\n",nameOrMove);
fflush(stdout);
if (nameOrMove == 0) { // name
int bytesRead, playerNameLen = 0;
char playerName[20],c;
bzero(playerName,20);
if( -1 == read(p[0], &playerNameLen, sizeof(int)))
{
perror("Error at reading from pipe.\n");
return errno;
}
if( -1 == read(p[0], playerName, playerNameLen))
{
perror("Error at reading from pipe.\n");
return errno;
}
printf("Playername: %s\n", playerName);
fflush(stdout);
//mesaj de raspuns pentru client
bzero(msgrasp,100);
strcat(msgrasp,"Hello ");
strcat(msgrasp,playerName);
printf("[server]Trimitem mesajul inapoi...%s\n",msgrasp);
fflush(stdout);
if(-1 == write(player1_fd, msgrasp, sizeof(msgrasp)))
{
perror("Error at writing to player1");
return errno;
}
printf("Player name sent\n");
fflush(stdout);
}
}
else{ //player 2
int nameOrMove;
if (-1 == read(p[0], &nameOrMove, sizeof(int))) // reading the name or move int
{
perror("Error at reading from pipe\n");
return errno;
}
printf("nameormove:%d\n",nameOrMove);
fflush(stdout);
if (nameOrMove == 0) { // name
int bytesRead, playerNameLen = 0;
char playerName[20],c;
bzero(playerName,20);
if( -1 == read(p[0], &playerNameLen, sizeof(int)))
{
perror("Error at reading from pipe.\n");
return errno;
}
if( -1 == read(p[0], playerName, playerNameLen))
{
perror("Error at reading from pipe.\n");
return errno;
}
printf("Playername: %s\n", playerName);
fflush(stdout);
//mesaj de raspuns pentru client
bzero(msgrasp,100);
strcat(msgrasp,"Hello ");
strcat(msgrasp,playerName);
printf("[server]Trimitem mesajul inapoi...%s\n",msgrasp);
fflush(stdout);
printf("p2fd: %d\n", player2_fd);
fflush(stdout);
// ----- !!! LINE 297 !!! -----
if(-1 == write(player2_fd, msgrasp, sizeof(msgrasp)))
{
perror("Error at writing to player1");
return errno;
}
printf("Player name sent\n");
fflush(stdout);
}
}
}
}
}
nrOfChilds++;
} else { // if it's the second player to be assigned to a waiting player 1
if (pid > 0) {
/* All messages from parent to it's children processes will start with a char
* that shows if it's information coming from an already connected player or the fd of a new connection:
* '0' - old client
* '1' - new client
* If the first char = '0', it will be followed by a char specifying from which player is the info coming from:
* '1' - player1
* '2' - player2
* The third char tells me if I'm getting the name of the player or a move:
* '0' - name
* '1' - move
*/
int x = 1;
if (-1 == write(child_fd[nrOfChilds-1].pipe[1], &x, sizeof(int)))
{
perror("Error at writing in pipe\n");
return errno;
}
if (-1 == write(child_fd[nrOfChilds-1].pipe[1], &client, sizeof(int))) //sending player2 socket descriptor to it's child process handler
{
perror("Error at writing in pipe\n");
return errno;
}
child_fd[nrOfChilds-1].player2_fd = client; //adding it to struct so the parent knows both players associated to each child process
}
}
}
/* vedem daca e pregatit vreun socket client pentru a trimite raspunsul */
if (pid > 0) {
for (fd = 0; fd <= nfds; fd++) /* parcurgem multimea de descriptori */
{
/* este un socket de citire pregatit? */
if (fd != sd && FD_ISSET (fd, &readfds)) {
for(int i = 0; i< nrOfChilds; ++i){ // looking for the child process to whom the client is associated
if ( fd == child_fd[i].player1_fd || fd == child_fd[i].player2_fd){
char nameOrMove;
if (-1 == read(fd, &nameOrMove, sizeof(char))) // reading the name or move char
{
perror("Error at reading from pipe\n");
return errno;
}
if (nameOrMove == '0') { // name
int bytesRead;
char playerName[20];
bytesRead = read (fd, playerName, sizeof (playerName));
if (bytesRead < 0)
{
perror ("Eroare la read() de la client.\n");
return errno;
}
int x = 0;
if ( -1 == write(child_fd[i].pipe[1], &x, sizeof(int))){
perror("Error at writing in pipe\n");
return errno;
}
x = (fd == child_fd[i].player1_fd) ? 1 : 2;
if ( -1 == write(child_fd[i].pipe[1], &x, sizeof(int))){
perror("Error at writing in pipe\n");
return errno;
}
x = 0;
if ( -1 == write(child_fd[i].pipe[1], &x, sizeof(int))){
perror("Error at writing in pipe\n");
return errno;
}
int playerNameLen = strlen(playerName);
if ( -1 == write(child_fd[i].pipe[1], &playerNameLen, sizeof(int))){
perror("Error at writing in pipe\n");
return errno;
}
if ( -1 == write(child_fd[i].pipe[1], playerName, playerNameLen)){
perror("Error at writing in pipe\n");
return errno;
}
}
FD_CLR(fd, &actfds);
}
}
}
}
}
/* for */
}
} /* while */
/* main */
One obvious bug that smashes the stack:
char msgrasp[20]=" ";
...
bzero(msgrasp,100);
Also don't use bzero, use standard C memset.