GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 12-Jul-2005, 09:06
j_kenpo j_kenpo is offline
New Member
 
Join Date: Jul 2005
Posts: 1
j_kenpo is on a distinguished road

Child Thread fails to update Shared Memory Correctly


I was wondering if someone where could help with this. I am working with Unix Shared Memory and BSD Sockets for the first time. I wrote a small little program that basically is supposed to take in multiple client connections, add their IP address to a class called "ChatClients", and then add this to a vector. The vector is created in the shared memory segment. The parent program can create this just fine, and the child can read the shared memory segment without any problems, however, when the forked child process attempts to add to the vector, or if the push back succeeds, read that element, the program hangs. Below is the code.

CPP / C++ / C Code:
/////////////////////////////////////////////////////////////////////////////////
/* A very simple chat server. Accepts connections, uses shared memory since I have never worked with
 * Shared memory before
*/


//needed for out networking functionality
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


//needed for the Shared Memory Functionality
#include <sys/ipc.h>
#include <sys/shm.h>

//Needed for our dynamic array type structure
#include <vector>

//console based IO library
#include <iostream>

//string library
#include <string>

//Our iterator class for the clients vector
#include <iterator>

//Classes for the clients connection
#include "../Classes/chatclient.h"

using namespace std;

//These are our function declarations
void error(const string &);

int main(int argc, char *argv[])
{
     //Variables for our network sockets
     int sockfd, newsockfd, portno, clilen, pid;
     struct sockaddr_in serv_addr, cli_addr;

     //Client information
     //Note: removed incoming_chat as a pointer and changed to regular variable, did not need to dynamically
     //allocate
     ChatClient incoming_chat; //pointer for incoming chat clients
     vector<ChatClient> *clients_vector; //Vector for storing the incoming clients
     
     //Variables for our Shared Memory Segment
     key_t key;
     int shmid;
    
     //The size of our shared memory segment, set to the size of the clients vector type * 1000
     int SHM_SIZE = sizeof(*clients_vector) * 1000;
    
     //Be verbose, let the console know how large the shared memory segment is set to
     cout << "Size of Shared Memory Segment: " << SHM_SIZE << endl;
     
     //We do not want any geeky stuff happening with the child processes later on, so set this up so that
     //the parent does not need to wait for the child to terminate
     signal(SIGCLD, SIG_IGN);
   
     //If there are not the appropriate command line options, exit the program
     if (argc < 2) {
         cerr << "ERROR, no port provided on the command line" << endl;
         exit(1);
     }

     //Create our shared memory key
     if ((key = ftok("server.cpp", 'J')) == -1) 
      		error("Failed to FTOK");
	
     //Connect to the shared memory segment and get the shared memory ID
     if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) 
	error("shmget attempt failed");
   
     // point the clients vector to the segment 
     clients_vector = (vector<ChatClient> *)shmat(shmid, NULL, 0);
     if (clients_vector == (vector<ChatClient> *)(-1))
        error("shmat failure");
       
     //Lets try and create a socket
     cout << "Initializing the servers socket" << endl;
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     
     //If the socket file descriptor is less than zero, an error occured, so exit gracefully
     if (sockfd < 0) 
        error("ERROR opening socket");

     //clear out the server address
     cout << "Zeroing out the server address structure" << endl;
     bzero((char *) &serv_addr, sizeof(serv_addr));
 
     //Take the port number and convert it into an integer
     cout << "Converting port number passed from command line to an integer" << endl;
     portno = atoi(argv[1]);
     
     //Set up our server information
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     
     //try and bind the socket file descriptor to the server
     cout << "Binding the socket" << endl;
     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     
     //Set up the socket to listen
     cout << "Binding succeeded, listening for incoming connections" << endl;
     listen(sockfd, 5);
    
     //Get the size of the client address struture for incoming connection.
     clilen = sizeof(cli_addr);
     
     //Lets see if this crashes our vector
     cout << endl << "Being memory test of chat client vector shared memory area" << endl;
     for (int x = 0; x < 100; x++)
     {
	   //cout << "Setting IP Address" << endl;
	   incoming_chat.set_ip_address("192.168.100.105");
	   
	   //cout << "Adding to vector" << endl;
	   clients_vector->push_back(incoming_chat);
	   
	   cout << "Vector count: " << clients_vector->size() << endl;
	   
	   cout << "Freeing memory" << endl;
     }

     cout << "Vector test succeeded, current vector size is: " << clients_vector->size() << endl;
     
     //Repeat indefinitly
     while (1) {
	 //For incoming connections, set the newsockfd to accept the incoming socket
         newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
	 cout << "Recieved Connections" << endl;
	 
         if (newsockfd < 0) 
             error("ERROR on accept");
         
	 //Since we have accpted the socket, fork a new process and exit
	 cout << "Forking Process" << endl;
	 pid = fork();
        
	 if (pid < 0)
             error("ERROR on fork");
	
	 if (pid == 0)  {
             //If this is the child socket, close out the main socket file descriptor to avoid problems
	     //and continue on with the newsockfd.
	     close(sockfd);
            
	     cout << "Size of vector from the start: " << clients_vector->size() << endl;
	     
	     //Get the IP Address of the incoming chat client
	     cout << "Setting the chat clients IP address" << endl;
	     incoming_chat.set_ip_address(inet_ntoa(cli_addr.sin_addr));
	    
	     cout << "Address of clients vector: " << clients_vector << endl;
	     
	     //Add our new chat request to the clients vector
	     cout << "Adding chat client to the clients vector" << endl;
	     clients_vector->push_back(incoming_chat);
	     
	     //Just a simple section to figure out what the hell is wrong with this stupid vector
	     vector<ChatClient>::iterator i;

	     int y = 0;
	     cout << "Preparing to go through each element in the vector to output" << endl; 
	     for (i = clients_vector->begin(); i <= clients_vector->end(); i++)
	    	cout << "Connection " << y++ << " from: " << i->get_ip_address() << endl;
	     
	     //output the vector size
	     cout << clients_vector->size() << endl;
	     
	     //generic do something section, just read in text message and echo back to the screen
	     char buffer[255];

	     bzero(buffer, 255);
	     if ((read(newsockfd,buffer,255)) < 0) 
		     error("ERROR reading from socket");
	     cout << "Here is the message: " << buffer << endl;
   	    
             if ((write(newsockfd,"I got your message\n",18)) < 0) 
		error("ERROR writing to socket"); 
	    
	     //Removed, the exit will detatch us from the segment automatically
	     /* detach from the segment: */
    	     //if (shmdt((char *)clients_vector) == -1) 
             //	error("shmdt");
     	    
	     //Exit child process
	     exit(0);
         }
         else
	     //Otherwise this is still the parent, and we do not want to interfere with the childs communication with its 
	     //client, so close the newsocket file descriptor
	     close(newsockfd);
     }
     
     return 0; /* we never get here */
}


//A generic function to print out error messages and panic out of the program
void error(const string &error)
{
	cerr << "Error has occured: " << error << endl;
	exit(1);
}
Last edited by admin : 12-Jul-2005 at 15:20. Reason: please insert your example C codes between [c] and [/c] bbcode tags
  #2  
Old 12-Jul-2005, 17:06
nkhambal nkhambal is offline
Regular Member
 
Join Date: Jul 2004
Location: CA USA
Posts: 313
nkhambal is a jewel in the roughnkhambal is a jewel in the rough
I think you should change this line

CPP / C++ / C Code:
 int SHM_SIZE = sizeof(*clients_vector) * 1000;

to

CPP / C++ / C Code:
 int SHM_SIZE = sizeof(ChatClient) * 1000;

Thanks,
 
 

Recent GIDBlogDeveloping GUIs with wxPython (Part 3) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
How to update the child dialog box Arbo MS Visual C++ / MFC Forum 1 01-Jun-2005 13:25
[Tutorial] Pointers in C (Part I) Stack Overflow C Programming Language 1 08-Apr-2005 18:35
shared memory and semaphores... socket C Programming Language 1 15-Feb-2004 09:54

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 12:14.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.