嗨,我在 C 中的客户端服务器程序遇到了这个问题。这应该是一个非常简单的预订系统......请有人可以帮助我,我不知道如何解决(C 中的第一个项目)。提前致谢
客户端.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define ERRORE -1
#define FLAG 0
#define SIZE 128
#define R 3
#define C 5
typedef struct {
int response_channel;
int service_code;
} request;
typedef struct {
long mtype;
request req;
} request_msg;
typedef struct {
long mtype;
int posti[R][C];
} response_msg;
/*strutture per cancella*/
typedef struct {
int response_channel;
int service_code;
char codice[5];
} request_canc;
typedef struct {
long mtype;
request_canc req;
} request_msg_canc;
typedef struct {
long mtype;
char risp[256];
} response_msg_canc;
//************************************************//
/* strutture per prenota*/
typedef struct {
int response_channel;
int service_code;
int posti[R][C];
} request_pren;
typedef struct {
long mtype;
request_pren req;
} request_msg_pren;
//**********************//
int my_id_coda,id_coda, ret, STATUS;
long key;
int sala[R][C];
request_msg request_message;
response_msg response_message;
/*variabili per cancella*/
request_msg_canc request_message_canc;
request_msg_pren posti_p;
void visualizza();
void prenota();
void cancella();
int menu();
main(int argc, char *argv[]) {
int scelta,ris;
key = getpid();
my_id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( my_id_coda == -1){
my_id_coda = msgget(key, IPC_CREAT|0666);
ret = msgctl(my_id_coda,IPC_RMID,0);
my_id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( my_id_coda == -1 ){
printf("cannot install client queue, please check with the problem\n");
exit(-1);
}
}
id_coda = msgget(50, IPC_CREAT|0666);
if( id_coda == -1 ){
printf("cannot open server queue, please check with the problem\n");
exit(-1);
}
/*qui mancava il richiamo al menu*/
do{
int a;
printf("1 visualizza;\n");
printf("2 prenota;\n");
printf("3 cancella;\n");
printf("4 esci;\n");
scanf("%d",&a);
scelta = a;
switch(scelta) {
case 1: visualizza(); break;
case 2: prenota(); break;
case 3: cancella(); break;
}
}while(scelta != 4);
ris=msgctl(my_id_coda,IPC_RMID,0);
if(ris==-1)printf("Errore nella chiamata msgctl");
exit(-1);
}/* end main*/
void visualizza() {
int i,j;
request_message.mtype = 1;
request_message.req.service_code = 1;
request_message.req.response_channel = my_id_coda;
printf("response channel has id %d\n",my_id_coda);
if ( msgsnd(id_coda, &request_message, sizeof(request), FLAG) == -1 ) {
printf("cannot send request to the server\n");
exit(-1);
}
if ( msgrcv(my_id_coda, &response_message, sizeof(response_msg), 1, FLAG) == -1) {
printf("error while receiving the server response, please check with the problem\n");
exit(-1);
}
else {
memcpy((char*)sala,(char*)response_message.posti,128);
printf("\nla sala è:\n");
for(i=0;i<R;i++){
for(j=0;j<C;j++){
printf("%d ",sala[i][j]);
}
printf("\n");
}
}
}
void prenota(){
int i,j;
int numero=0;
int fila=0;
int poltrona=0;
response_msg_canc risposta_codice;
for(i=0;i<R;i++)
for(j=0;j<C;j++)
posti_p.req.posti[i][j]=0;
numero=0;
while(numero>R*C || numero<=0){
printf("Digitare il numero di posti che si vuole prenotare compreso tra 1 e %d\n",R*C);
scanf("%d",&numero);
}
for(i=0;i<numero;i++){
printf("Digitare il %d° posto nel formato 'fila poltrona' con fila compresa tra 1..%d e poltrona tra 1..%d \n",i+1,R,C);
scanf("%d%d",&fila,&poltrona);
/*scanf("%d",&fila);
scanf("%d",&poltrona);*/
if(fila<=0 || fila>R || poltrona<=0 || poltrona>C){
printf("ERRORE\n");
i--;
}
else {posti_p.req.posti[fila-1][poltrona-1]=1;}
}
for(i=0;i<R;i++){
for(j=0;j<C;j++){
printf("%d",posti_p.req.posti[i][j]);
}
printf("\n");
}
posti_p.mtype = 2;
posti_p.req.service_code = 2;
posti_p.req.response_channel = my_id_coda;
if ( msgsnd(id_coda, &posti_p, sizeof(request_pren), FLAG) == -1 ) {
printf("cannot send request to the server\n");
exit(-1);
}
if ( msgrcv(my_id_coda, &risposta_codice, sizeof(response_msg_canc), 2, FLAG) == -1) {
printf("error while receiving the server response, please check with the problem\n");
exit(-1);
}
printf("%s\n",risposta_codice.risp);
}
/* metodo cancella*/
void cancella(){
int i,j;
char preno[5];
response_msg_canc risposta;
request_message_canc.mtype = 3;
request_message_canc.req.service_code = 3;
printf("Inserire codice prenotazione da cancellare:");
scanf("%s",preno);
strcpy(request_message_canc.req.codice,preno);
request_message_canc.req.response_channel = my_id_coda;
printf("response channel has id %d\n",my_id_coda);
if ( msgsnd(id_coda, &request_message_canc, sizeof(request_canc), FLAG) == -1 ) {
printf("cannot send request to the server\n");
exit(-1);
}
if ( msgrcv(my_id_coda, &risposta,sizeof(response_msg_canc), 3, FLAG) == -1) {
printf("error while receiving the server response, please check with the problem\n");
exit(-1);
}
risposta.risp[255]='\0';
printf("%s\n",risposta.risp);
}
服务器.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <math.h>
#include<stdlib.h>
#include<string.h>
#include <sys/sem.h>
#define ERRORE -1
#define FLAG 0
#define SIZE 128
#define R 3
#define C 5
#define CINEMA "prenotazione"
#define STDOUT 1
typedef struct {
int response_channel;
int service_code;
} request;
typedef struct {
int response_channel;
int service_code;
char codice[5];
} request_canc;
typedef struct {
long mtype;
request_canc req;
} request_msg_canc;
typedef struct {
long mtype;
request req;
} request_msg;
typedef struct {
long mtype;
int posti[R][C];
} response_msg;
typedef struct {
char pren[6];
} codice;
typedef struct {
long mtype;
char risp[256];
} response_msg_canc;
/* strutture per prenota*/
typedef struct {
int response_channel;
int service_code;
int posti[R][C];
} request_pren;
typedef struct {
long mtype;
request_pren req;
} request_msg_pren;
//**********************//
codice prenotazioni[R][C];
int id_coda, ret;
long key = 50;
request_msg request_message;
request_msg *new_message;
pthread_t tid;
response_msg response_message;
request_msg_canc request_mes_canc;
request_msg_canc *new_mes_canc;
request_msg_pren request_mes_pren;
request_msg_pren *new_mes_pren;
int ds_shm;
int id_sem;
void ito(int,char*);
int crea_init_sem(key_t,int);
void elimina_sem(int);
int sem_wait(int);
int sem_signal(int);
void visualizza(request_msg*);
void prenota (request_msg_pren*);
void cancella (request_msg_canc*);
main(int argc, char *argv[]) {
codice prenot[3][5];
int sd,size,occ,i,j,status,eli;
long chiave=10,chiave_sem=50;
char buff[5],app[5],*p,*scorri_mem;
sd=open(CINEMA,O_RDONLY);
ds_shm = shmget(chiave,sizeof(codice[3][5]),IPC_CREAT|0666);
if( ds_shm == -1) {printf("Errore nella chiamata shmget\n"); exit(1);}
p = shmat(ds_shm, 0, SHM_W);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
size=read(sd,buff,5);
memcpy((char*)app,(char*)buff,size);
strncpy(scorri_mem,app,5);
*(scorri_mem+5)='\0';
printf("%s",scorri_mem);
scorri_mem+=6;
}
}
id_sem=crea_init_sem(chiave_sem,1);
id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( id_coda == -1){
id_coda = msgget(key, IPC_CREAT|0666);
ret = msgctl(id_coda,IPC_RMID,0);
id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( id_coda == -1 ){
printf("cannot install server queue, please check with the problem\n");
exit(-1);
}
}
//close(sd);
if(fork()==0){
while(1) {
if ( msgrcv(id_coda, &request_message, sizeof(request), 1, FLAG) == -1) {
printf("message receive error, please check with the problem\n");
}
else {
new_message = malloc(sizeof(request_msg));
if(!new_message){
printf("cannot allocate new request message buffer \n");
exit(-1);
}
memcpy((char*)new_message,(char*)&request_message,sizeof(request_msg));
if( pthread_create(&tid, NULL, visualizza, (void *)new_message) != 0){
printf("cannot create new thread \n");
exit(-1);
}
}
}/* end while */
}/* end fork*/
// prenota
if(fork()==0){while(1) {
if ( msgrcv(id_coda, &request_mes_pren, sizeof(request_pren), 2, FLAG) == -1) {
printf("message receive error, please check with the problem\n");
}
else {
new_mes_pren = malloc(sizeof(request_msg_pren));
if(!new_mes_pren){
printf("cannot allocate new request message buffer \n");
exit(-1);
}
memcpy((char*)new_mes_pren,(char*)&request_mes_pren,sizeof(request_pren));
if( pthread_create(&tid, NULL, prenota, (void *)new_mes_pren ) != 0){
printf("cannot create new thread \n");
exit(-1);
}
}
}/* end while */
}/* end fork*/
// cancella
if(fork()==0){ while(1) {
if ( msgrcv(id_coda, &request_mes_canc, sizeof(request_canc), 3, FLAG) == -1) {
printf("message receive error, please check with the problem\n");
}
else {
new_mes_canc = malloc(sizeof(request_msg_canc));
if(!new_mes_canc){
printf("cannot allocate new request message buffer \n");
exit(-1);
}
memcpy((char*)new_mes_canc,(char*)&request_mes_canc,sizeof(request_canc));
if( pthread_create(&tid, NULL, cancella, (void *)new_mes_canc ) != 0){
printf("cannot create new thread \n");
exit(-1);
}
}
}/* end while */
}/* end fork*/
wait(&status);
eli=msgctl(ds_shm,IPC_RMID,NULL);
if(eli == -1) printf("Errore nella chiamata msgctl");
elimina_sem(id_sem);
}
void visualizza(request_msg *request_message){
int status,i,j,occ;
char *p;
printf("asked service of type %d - response channel is %d\n", request_message->req.service_code,request_message->req.response_channel);
response_message.mtype = 1;
p = shmat(ds_shm, 0, SHM_R);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
for(i=0;i<R;i++){
for(j=0;j<C;j++){
strncpy(prenotazioni[i][j].pren,p,6);
p+=6;
}
}
for(i=0;i<R;i++)
for(j=0;j<C;j++){
occ=strncmp(prenotazioni[i][j].pren,"0000",4);
if(occ==0) response_message.posti[i][j]=0;
else response_message.posti[i][j]=1;
}
if ( msgsnd(request_message->req.response_channel, &response_message, sizeof(response_msg), FLAG) == -1 ) {
printf("cannot return response to the client\n");
exit(-1);
}
i=shmdt(p);
free(request_message);
status = 0;
pthread_exit((void *)&status);
}
void prenota (request_msg_pren *request_mes_pren){
response_msg_canc risposta_pren;
int status,occ,i,j,dist,trovato,cod,sd,doppio,conta=0;
char *p,c[6],*scorri_mem;
risposta_pren.mtype = 2;
sem_wait(id_sem);
p = shmat(ds_shm, 0, SHM_R);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
strncpy(prenotazioni[i][j].pren,scorri_mem,6);
scorri_mem+=6;
}
}
scorri_mem=p;
for(i=0;i<R;i++)
for(j=0;j<C;j++){
occ=strncmp(prenotazioni[i][j].pren,"0000",4);
if(occ==0) response_message.posti[i][j]=0;
else response_message.posti[i][j]=1;
}
for(i=0;i<R;i++)
for(j=0;j<C;j++){
if(request_mes_pren->req.posti[i][j]==1)
if(request_mes_pren->req.posti[i][j]==response_message.posti[i][j])
trovato=1;
if(request_mes_pren->req.posti[i][j]==0) conta++;
}
i=shmdt(p);
p = shmat(ds_shm, 0, SHM_R);
scorri_mem=p;
if(trovato==1 || conta==(R*C)){ strcpy(risposta_pren.risp,"prenotazione non effettuata");}
else {
do{
cod=random();
ito(cod,c);
doppio=0;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
occ=strncmp(prenotazioni[i][j].pren,c,4);
if(occ==0) {doppio=1;break;}
}
}
}while(doppio==1);
strcpy(risposta_pren.risp,"prenotazione effettuata con codice: ");
strncat(risposta_pren.risp,c,6);
i=shmdt(p);
p = shmat(ds_shm, 0, SHM_W);
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
if(request_mes_pren->req.posti[i][j]==1){
strncpy(scorri_mem,c,6);
if(j<(C-1)) *(scorri_mem+4)=' ';
else (*(scorri_mem+4)='\n');
}
*(scorri_mem+5)='\0';
scorri_mem+=6;
}
}
}
close(STDOUT);
scorri_mem=p;
sd=open(CINEMA,O_RDWR|O_TRUNC);
dup(sd);
for(i=0;i<R;i++){
for(j=0;j<C;j++){
write (sd,scorri_mem,5);
scorri_mem+=6;
}
}
//fflush(STDOUT);
if ( msgsnd(request_mes_pren->req.response_channel, &risposta_pren, sizeof(response_msg_canc), FLAG) == -1 ) {
printf("cannot return response to the client\n");
exit(-1);
}
close(sd);
sem_signal(id_sem);
free(request_mes_pren);
status = 0;
pthread_exit((void *)&status);
}
void cancella (request_msg_canc *request_mes_canc){
response_msg_canc risposta;
int status,occ,i,j,dist,sd,trovato=0;
char *p,*scorri_mem;
risposta.mtype = 3;
p = shmat(ds_shm, 0, SHM_W);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
scorri_mem=p;
for(i=0;i<R;i++)
for(j=0;j<C;j++){
occ=strncmp(scorri_mem,request_mes_canc->req.codice,4);
if(occ==0) {
trovato++;
if(j<C-1){ strcpy(scorri_mem,"0000 \0");}
else { strcpy(scorri_mem,"0000\n");}
}
scorri_mem+=6;
}
i=shmdt(p);
sd=open(CINEMA,O_RDWR|O_TRUNC);
p = shmat(ds_shm, 0, SHM_R);
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
write(sd,scorri_mem,5);
scorri_mem+=6;
}
}
if(trovato>0) strcpy(risposta.risp,"cancellazione effettuata");
else { strcpy(risposta.risp,"codice inesistente");}
if ( msgsnd(request_mes_canc->req.response_channel, &risposta, sizeof(response_msg_canc), FLAG) == -1 ) {
printf("cannot return response to the client\n");
exit(-1);
}
close(sd);
i=shmdt(p);
free(request_mes_canc);
status = 0;
pthread_exit((void *)&status);
}
void ito(int casuale,char c[]){
div_t divisione;
int i,k,j,num=1;
if(casuale > 999999999) k=9;
else k=8;
for(j=0;j<k;j++)
num=num*10;
for(i=0;i<4;i++){
divisione= div(casuale,num);
switch(divisione.quot) {
case 0: c[i]='0'; break;
case 1: c[i]='1'; break;
case 2: c[i]='2'; break;
case 3: c[i]='3'; break;
case 4: c[i]='4'; break;
case 5: c[i]='5'; break;
case 6: c[i]='6'; break;
case 7: c[i]='7'; break;
case 8: c[i]='8'; break;
case 9: c[i]='9'; break;
}
casuale=divisione.rem;
num=num/10;;
}
c[4]=' ';
c[5]='\0';
return ;
}
int crea_init_sem(key_t chiave, int val)
{
int sem;
sem=semget(chiave,1,IPC_CREAT|0666);
if (sem==-1)
{
printf("Impossibile creare il semaforo\n");
exit(1);
}
semctl(sem,0,SETVAL,val);
return(sem);
}
void elimina_sem(int id_sem)
{
if(semctl(id_sem,IPC_RMID,0)==-1)
{
printf("Impossibile eliminare il semaforo\n");
exit(1);
}
}
int sem_wait(int sem)
{
struct sembuf operazione[1]={{0,-1,0}};
return semop(sem,operazione,1);
}
int sem_signal(int sem)
{
struct sembuf operazione[1]={{0,+1,0}};
return semop(sem,operazione,1);
}
这就是崩溃:
*** stack smashing detected ***: ./Client
======= Memory map: ========
uca@luca-8:~/Scrivania/tesina/ufficial$ ./Client
1 visualizza;
2 prenota;
3 cancella;
4 esci;
2
Digitare il numero di posti che si vuole prenotare compreso tra 1 e 15
2
Digitare il 1° posto nel formato 'fila poltrona' con fila compresa tra 1..3 e poltrona tra 1..5
3 1
Digitare il 2° posto nel formato 'fila poltrona' con fila compresa tra 1..3 e poltrona tra 1..5
3 2
00000
00000
11000
prenotazione effettuata con codice: 1804
*** stack smashing detected ***: ./Client terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0x9408d5]
/lib/i386-linux-gnu/libc.so.6(+0xe7887)[0x940887]
./Client[0x8048c8d]
./Client[0x80487aa]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x872113]
./Client[0x80485c1]
======= Memory map: ========
0019d000-0019e000 r-xp 00000000 00:00 0 [vdso]
00525000-00541000 r-xp 00000000 08:01 2360250 /lib/i386-linux-gnu/libgcc_s.so.1
00541000-00542000 r--p 0001b000 08:01 2360250 /lib/i386-linux-gnu/libgcc_s.so.1
00542000-00543000 rw-p 0001c000 08:01 2360250 /lib/i386-linux-gnu/libgcc_s.so.1
00859000-009cf000 r-xp 00000000 08:01 2360229 /lib/i386-linux-gnu/libc-2.13.so
009cf000-009d1000 r--p 00176000 08:01 2360229 /lib/i386-linux-gnu/libc-2.13.so
009d1000-009d2000 rw-p 00178000 08:01 2360229 /lib/i386-linux-gnu/libc-2.13.so
009d2000-009d5000 rw-p 00000000 00:00 0
00b18000-00b36000 r-xp 00000000 08:01 2360216 /lib/i386-linux-gnu/ld-2.13.so
00b36000-00b37000 r--p 0001d000 08:01 2360216 /lib/i386-linux-gnu/ld-2.13.so
00b37000-00b38000 rw-p 0001e000 08:01 2360216 /lib/i386-linux-gnu/ld-2.13.so
08048000-0804a000 r-xp 00000000 08:01 5636693 /home/luca/Scrivania/tesina/ufficial/Client
0804a000-0804b000 r--p 00001000 08:01 5636693 /home/luca/Scrivania/tesina/ufficial/Client
0804b000-0804c000 rw-p 00002000 08:01 5636693 /home/luca/Scrivania/tesina/ufficial/Client
0809c000-080bd000 rw-p 00000000 00:00 0 [heap]
b78b1000-b78b2000 rw-p 00000000 00:00 0
b78bf000-b78c3000 rw-p 00000000 00:00 0
bf8d0000-bf8f1000 rw-p 00000000 00:00 0 [stack]
Annullato
luca@luca-8:~/Scrivania/tesina/ufficial$