You are here:

C++/A question about bank transactions

Advertisement


Question
QUESTION: Hi,
first of all I would like to apologise that I am writing to you a private message.
But I believe that you could help me.

I am trying to make a application like yours in C with sockets.

But the problem I have is first time server communicates with client but then no.

Could I send you my code to help me ?
please


ANSWER: > I am trying to make a application like yours in C with sockets.

Which application are you talking about?

> Could I send you my code to help me ?

Yes, you could post the code - not the code for the whole program, but an extract of the part that you are having a problem with. The part that deals with creating a socket, connecting to a server, sending and receiving data and closing the socket.

Clearly mark out, via a few descriptive lines and code comments, exactly at what point in the code you are encountering a problem.

Also, do not forget to identify the platform (eg. FreeBSD 7.1 i386 or Windows XP SP2) and the compiler (eg. GCC 4.4.2)




---------- FOLLOW-UP ----------

QUESTION: I don't know where exactly in code is my problem.I can't understand.
The problem I have is an user(client) press his choice for creating an account, making a deposit or quit.
The first time when client press 1, server is updated and prints create.
When menu is opening again and press 1, server does not print something.
Do you know what happens ?


My code is :

client.c
#include <errno.h>
#include <sys/types.h>     
#include <sys/socket.h>    
#include <sys/un.h>        
#include <stdio.h>         
#include <stdlib.h>      
#include <time.h>

#include "client_functions.h"

#define SOCKET_ERROR    -1
#define MAX_CHARACTER   15

enum BANK{ TERMATISMOS=0 , DHMIOURGIA=1, KATATHESH=2} OPERATIONS;


int write_success_in_array(int, char*, int, char[]);



main(int argc, char *argv[])
{
  int sock,serverlen;
  char buf[300];
  int choice ;
  char name[MAX_CHARACTER];
  char surname[MAX_CHARACTER];
  int initial_sum;

  int i,in;
  short s,sn;

  int epilogi_anazitisis_katathesis;
  int id_anazitisis;

  struct sockaddr_un server;
  struct sockaddr *serverptr;

  if(argc != 2){
     printf("\nError socket filename.\n\n");
     exit(1);
  }

  if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) ==  SOCKET_ERROR){
     printf("client socket failure %d\n",errno);
     perror("socket");
     exit(1);
  }

  server.sun_family = AF_UNIX;
  strcpy(server.sun_path, argv[1]);
  
  serverptr = (struct sockaddr *) &server;
  serverlen = sizeof server;

  if(connect(sock,serverptr,serverlen) ==  SOCKET_ERROR){
     printf("client connect failure %d\n",errno);
     perror("Client: ");
     exit(1);
  }//telos if pou kaleitai h connect   


  

  do{
         
     display_menu_operations(argv[1]) ;
     choice = get_choice();
        
     
     switch(choice)
         {
         case DHMIOURGIA:  print_string_in_frame("Create");

         write_success_in_array(sock,buf,sizeof buf,"dhmiourgia");

         strcpy(name,get_personal_elements("name")); //apothikeuoume to onoma sth metavlhth name //
         strcpy(surname,get_personal_elements("surname")); //apothikeuoume to epwnumo sth metavlhth surname
         initial_sum = get_number(0); //apothikeuoume to arxiko poso sth metavlhth initial_sum

         write_success_in_array(sock,buf,sizeof buf,name);
         write_success_in_array(sock,buf,sizeof buf,surname);
         
         in = htonl(initial_sum);
         bzero(buf,sizeof buf);
         write(sock,&in,sizeof in);
         
         break ;



         case KATATHESH:  print_string_in_frame("deposit");

         write_success_in_array(sock,buf,sizeof buf,"katathesh");
         break ;



         case TERMATISMOS:  print_string_in_frame("\tquit");
         bzero(buf,sizeof buf);
         strcpy(buf,"end");
         write(sock,buf,sizeof buf);     
         break;
      }
       
  }while(choice!=0); //oso h epilogh den einai 0(=TERMATISMOS apo enum)   


  close(sock); //eleutherwsh perigrafea fd

}//telos main



int write_success_in_array(int fd, char *buf, int count, char array[])     
{
   
    bzero(buf,count);  //mhdenismos buffer
    strcpy(buf,array); //apothikeush array ston buf
   
   if (write(fd,buf,count) == SOCKET_ERROR )
  {
     printf("client write failure %d\n",errno);
     perror("Client: ");
     exit(1);
  }

}


client_functions.h
#define MAX_CHARACTER 15

void display_menu_operations(char *s)
{

  time_t timer;
  timer = time(NULL);

  printf("\t  %s",asctime(localtime(&timer)));
  printf("***************************************************\n");
  
  printf("Press :\n");
  printf("1. create account.\n");
  printf("2. deposit.\n");
  printf("0. quit.\n\n");

} //telos display_menu_operations


int get_choice()
{
   int choice = 0;
  do{   
     printf("Insert choice : ");
     scanf("%d",&choice);

  } while((choice!=1)&&(choice!=2)&&(choice!=0));
  

}//telos get_choice

void print_string_in_frame(char *str)
{
  printf("\n----------------------------\n");
  printf("%s\n",str);
  printf("-----------------------------\n\n");

}//telos print_string_in_frame



char *get_personal_elements(char *str)
{

  int len;
  char *ptr;

  if(str == "name")
  {
     printf("name : ");
     char name[50];

     do{
        scanf("%s",name);
         len = strlen(name);
        
        if(len > MAX_CHARACTER)
        {
         printf("Maximum 15  chars : ");
        }

        ptr = name;

     }while(len > MAX_CHARACTER);
  
  
      
  }else if(str == "surname"){
  
     printf("surname : ");
     char surname[50];

     do{
        scanf("%s",surname);
        len = strlen(surname);     
        
        if(len >  MAX_CHARACTER)
        {
         printf("Maximum 15 chars : ");
        }

     ptr = surname;

     }while(len >  MAX_CHARACTER);

  
  }
  
return ptr;
}

int get_number(int i)
{
  int number;

  if(i==0)
     printf("amount : ");
  else
     printf("Id : ");

  scanf("%d",&number);
  
return number;
}

display_serve_info.h

void display_server_info()
{

  time_t timer;
  timer = time(NULL);

  printf("\t %s",asctime(localtime(&timer)));
  printf("***************************************************\n");

  printf("\nI am waiting  . . .\n");

}


server.c

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <time.h>

#include "display_server_info.h"

#define ALWAYS        1
#define SOCKET_ERROR    -1
#define BUFFER_SIZE   300
#define MAX_CHARACTER    15
#define MAX_ACCOUNTS   300

void sigchld_handler();


int read_success_buffer(int, char*, int);

typedef struct account account ;
struct account
{
  char onoma[MAX_CHARACTER] ;
  char epwnumo[MAX_CHARACTER] ;
  int aukswn_arithmos ;
  int ypoloipo ;
};

int id = 0;


int create_account(account* accounts, int id,char name[],char surname[], int initial_sum)
{
   if(id == MAX_ACCOUNTS)
   {
     puts("not anymore accounts") ;
     return 0;
   }else{
        account* ac = accounts + id ;
        strcpy(ac->onoma,name);
         strcpy(ac->epwnumo,surname);
         ac->ypoloipo = initial_sum;
     id=id+1;
     ac->aukswn_arithmos = id;
        return 1 ;
   }
}

main(int argc, char *argv[])
{
  int sock,newsock,serverlen,clientlen;
  char buf[BUFFER_SIZE];

  int in,initial_sum;
  
  time_t timer;
  timer = time(NULL);

  account accounts[ MAX_ACCOUNTS ] ;
  char name[15];
  char surname[15];

  struct sockaddr_un server, client;
  struct sockaddr *serverptr, *clientptr;

  
  if(argc != 2){
     printf("\nError  socket filename.\n\n");
     exit(1);
  }

  signal(SIGCHLD, sigchld_handler);

  
  if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) ==  SOCKET_ERROR){
     printf("server socket failure %d\n",errno);
     perror("Server: ");
     exit(1);
  }//telos if pou kaleitai h socket


  server.sun_family = AF_UNIX;
  strcpy(server.sun_path, argv[1]);
  unlink(argv[1]);
  serverptr = (struct sockaddr *) &server;
  serverlen = sizeof server;


  if(bind(sock,serverptr,serverlen) ==  SOCKET_ERROR ){
     printf("server bind failure %d\n",errno);
     perror("Server: ");
     exit(1);
  }//telos if pou kaleitai h bind
  

  if(listen(sock,1) ==  SOCKET_ERROR){
     printf("server listen failure %d\n",errno);
     perror("Server: ");
     exit(1);
  }


  display_server_info();
     
  while(ALWAYS){
     clientptr = (struct sockaddr *)&client;
     clientlen = sizeof client;

        
         while((newsock = accept(sock,clientptr,&clientlen)) ==  SOCKET_ERROR );
     printf("*************** new connection. ***************\n");
         
     
  
     switch(fork()){

        case -1 :
         printf("server fork failure %d\n",errno);
         perror("Server: ");
         exit(1);

        case 0 :
         do{

         
         read_success_buffer(newsock,buf,sizeof buf);
         
         if(strcmp(buf,"dhmiourgia")==0)
         {

         printf("\n --> create account.\n",buf);
         
         
         read_success_buffer(newsock,buf,sizeof buf);
         strcpy(name,buf);

         
         read_success_buffer(newsock,buf,sizeof buf);
         strcpy(surname,buf);

         bzero(buf,sizeof buf);
         read(newsock,&in,sizeof in);
         initial_sum = ntohl(in);
         
         create_account(accounts,id,name,surname,initial_sum);
         printf("id = %d\n", accounts[0].aukswn_arithmos);
         printf("name = %s  %s\n", accounts[0].onoma,accounts[0].epwnumo);
         printf("amount %d\n",accounts[0].ypoloipo);
         
         
         
         }else if(strcmp(buf,"katathesh")==0){

         printf("\n --> deposit.\n",buf);

         }

         
         
         if(close(newsock) ==  SOCKET_ERROR)
         {
         printf("server close failure %d\n",errno);
         perror("Server: ");
         exit(1);
         }

         exit(0);

         }while(strcmp(buf,"end")!=0);
         

     }


  }

}


void sigchld_handler()
{
  int status;
  wait(&status);
}


  
int read_success_buffer(int fd, char *buf, int count)     
{
   
    bzero(buf,count);
   
   if (read(fd,buf,count) == SOCKET_ERROR )
  {
     printf("server read failure %d\n",errno);
     perror("Server: ");
     exit(1);
  }
}









ANSWER: The structure of your client code is:

1. create a socket => sock = socket( AF_UNIX, SOCK_STREAM, 0 )
2. Connect to the server => connect( sock, serverptr, serverlen )
3. loop => do {
     4. accept user choice
     5. switch on choice, if choice is quit then break out of loop
     6. else process create, deposit requests
     7. repeat loop from step for
8. end loop
9. Close the socket => close(sock);



The structure of your server code is:

1. create a socket => with sock = socket( AF_UNIX, SOCK_STREAM, 0 )
2. Bind to an address => bind( sock, serverptr, serverlen )
3. Listen for incoming connections => listen( sock, 1 )
    incidentally, giving a larger backlog is advisable: listen( sock, 1 )

4. Loop for ever=>  while(ALWAYS) {
     5. accept a connection from the client => newsock = accept( sock, clientptr, &clientlen )
     6. fork a child process => fork()
         In the child process:
         7. Read in a request => read_success_buffer( newsock, buf, sizeof buf )
         8. Check the request type and process it => if( strcmp( buf, "dhmiourgia" ) == 0 ) etc.
         9. Close the connection => close(newsock)

There is a problem here:
   The server parent process does not close the new socket => newsock
   The client connected can therefore reuse the socket.
   But accept is called each time in the loop => accept( sock, clientptr, &clientlen ). That is, you are
       trying to accept a fresh connection each time in the loop.

Move the accept call to outside the loop while(ALWAYS) and you should be Ok.

WARNING: I've only looked at the socket portion of your code. I've not tested the program or looked at any of the functions other than main for client and server.
   




---------- FOLLOW-UP ----------

QUESTION: You are really expert.

My final question I would like to use shared memory only in server.
The code is something like that ??

intshm_id, error;
char*data;

shm_id= shmget(SHM_KEY, SHM_SIZE, 0600| IPC_CREAT);
data = shmat(shm_id, NULL, 0);

while(newsock = accept( sock, clientptr, &clientlen ));

while(1)
{


  if(fork()==1)
 {
    //here I have to write in memory
    // with  strncpy(data, "string", SHM_SIZE);
    // and all is ok ???
    // I want to save name,surname,id and amount in a memory

 }

}

Thanks for all!  

Answer
Yes, that should be fine.

One issue that you may want to address is that of concurrency - if many processes or threads try to write into the shared memory at the same time, the data could get corrupted. If that is a possibility, you would need to synchronize access to the shared memory - for example, by using a semaphore.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


vijayan

Expertise

my primary areas of interest are generic and template metaprogramming, STL, algorithms, design patterns and c++11. i would not answer questions about gui and web programming.

Experience

about 15 years or so

Education/Credentials
post graduate engineer

©2016 About.com. All rights reserved.