Hello all,
after searching for documentation and tutorials along the web (including this forum) I was not able to find a solution to an issue I am having with a linux server.
The idea is to have a server which will handle sockets using multithreading processes.
The child will handle socket connection and later the data should be sent to the parent process.
For some reason, it's only handling 1 client.
I want the parent process to handle data so the "kid" should be able to manage connections.
Once the data is being handled, the parent will send away the data directly to client and not through child process.
Here I have a basic scheme:
incoming data:
CLIENT --><SOCKET>-->CHILD PROCESS--><PIPE>-->PARENT PROCESS
outgoing data:
PARENT PROCESS --> <SOCKET> --> CLIENT
So far I got this code:
Code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/msg.h>
#include <wait.h>
// Max number of clients
int max_cli=5;
// Future menu options
char *opt;
// Error messages
void error(const char *msg){
perror(msg);
exit(-1);
}
// --------> Multithreading
/* ChildProcess */
pid_t idProcess;
/* Returned balue by ChildProcess */
int childStatus;
// --------> PIPES code
//
// Structure for messages that are going to be sent/received. They must
// have "long" field to have an identifier of message.
// Following fields are information to be transmitted in the message.
// Later once we type cast the value (struct msgbuf *), all the fields will be seen as an unique (char *)
//
typedef struct
{
long Id_Message;
char Message[1024];
} A_Message_Type;
key_t Key1;
int Id_Message_Queue;
A_Message_Type A_Message;
void SonTasks(int); /* function prototype */
void ParentTasks(); /* function prototype */
/* Before calling fork(), we create the pipe with 2 descriptors,
* for I/O purposes */
/* We will set values: 0->IN 1->OUT */
int pipeDescriptor[2];
/* This will be our buffer to write in the PIPE */
char buffer[1024];
// --------> Main
int main(int argc, char *argv[]){
printf("Loading server...\n\n");
//********************* SOCKETS
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
error("ERROR, no port provided");
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,max_cli);
clilen = sizeof(cli_addr);
//*****************************
//
// As in other shared resource (Shared memory, Semaphor
// or queues) we get a key from an exiting file
// and an integer number. All the processes who want to share this
// semaph. should use same file and same integer number.
//
printf("Creating key for queues... ");
Key1 = ftok ("/bin/ls", 33);
if (Key1 == (key_t)-1){
error("Error");
}
printf("[OK]\n");
//
// We create a queue for messages.
//
printf("Getting identifier for queues... ");
Id_Message_Queue = msgget (Key1, 0600 | IPC_CREAT);
if (Id_Message_Queue == -1){
error("Error");
}
printf("[OK]\n");
if (pipe (pipeDescriptor) == -1){
error("Error");
}
while(opt!="shutdown"){
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
printf("ERROR on accept\n"); // Even if we find an error the server must not stop
idProcess = fork();
switch (idProcess){
case -1:
error("Failed to create process");
break;
case 0:
//close(sockfd);
SonTasks(newsockfd);
break;
default:
//close(newsockfd);
ParentTasks();
break;
}
}
close(sockfd);
return 0; /* We will never reach this point */
}
/******** SonTasks() *********************
There is a separate instance of this function
for each connection. It handles all communication
once a connnection has been established.
*****************************************/
void SonTasks(int sock){
char BufferChild[1024];
// ****** SOCKETS
int n;
// **************
while(1){
// ************ SOCKETS
bzero(BufferChild,1024);
n = read(sock,BufferChild,1023);
if (n < 0) printf("ERROR reading from socket\n");
printf("Received from socket: %s",BufferChild);
//if (n < 0) printf("ERROR writing to socket for client %d", sock);
// ********************
// **** SENDING DATA THROUGH PIPE
/* Close reading descriptor since we are not going to use it for child process */
close (pipeDescriptor[0]);
/* We write through the "writing" descriptor */
write (pipeDescriptor[1], BufferChild, strlen(BufferChild)+1);
}}
/******** ParentTasks() *********************
There is only one instance of this function
for all connections.
*****************************************/
void ParentTasks(){
char buffer[1024];
while(1){
bzero(buffer,1024);
/* Close writing descriptor since we are not going to use it for parent process */
close (pipeDescriptor[1]);
/* We read all characters from reading descriptor and will print it on screen */
read (pipeDescriptor[0], buffer, 1023);
printf ("Received from my son: %s", buffer);
/* We wait until the son dies and we leave (parricide??) */
wait (&childStatus);
}
}
What could I do with this?
thanks in advance