Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* SISTC T4 - Aplicação multi-thread */
- // Apple Xcode
- // func.c
- #include "func.h"
- #include <stdio.h>
- #include <string.h>
- #include <signal.h>
- #include <sys/wait.h>
- #include <errno.h>
- void ler_registo(veiculo_t *v)
- {
- char the_aux[8];
- printf("\nmatricula: ");
- // get a line from a stream
- fgets(the_aux, 8, stdin);
- // copy memory area
- memcpy(v->matricula, the_aux, 6);
- printf("\nproprietario: ");
- // get a line from a stream
- fgets(v->proprietario, NAME_BUFFER_SIZE, stdin);
- v->apagado = '0';
- }
- void imprimir_registo(veiculo_t *v)
- {
- if (v->apagado == '0')
- {
- printf("\nproprietario\n %s ", v->proprietario);
- printf("\n matricula\n");
- fwrite(v->matricula, 6, 1, stdout);
- }
- }
- void apagar_registo(char matricula[], FILE *the_record)
- {
- veiculo_t v1;
- // binary stream input/output
- while (fread(&v1, sizeof(v1), 1, the_record) != 0)
- {
- // compare strings
- if (strncmp(matricula, v1.matricula, 6) == 0)
- {
- v1.apagado = '1';
- // reposition a stream
- fseek(the_record, -sizeof(v1), SEEK_CUR);
- fwrite(&v1, sizeof(v1), 1, the_record);
- }
- }
- }
- //
- // func.h
- #include <stdio.h>
- #define NAME_BUFFER_SIZE 80
- typedef struct
- {
- char matricula[6];
- char proprietario[NAME_BUFFER_SIZE];
- char apagado;
- } veiculo_t;
- void ler_registo(veiculo_t *);
- void imprimir_registo(veiculo_t *);
- void apagar_registo(char *, FILE *);
- //void sigchld_handler(int);
- //
- // main.c
- // servidor
- #include "func.h"
- #include <stdio.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #include <arpa/inet.h>
- #include <pthread.h>
- #include <semaphore.h>
- #define PROP "proprietario"
- void atende_pedido(int);
- int prepara_socket_servidor(int the_port);
- int the_request = 0;
- int the_count = 0;
- // to define a semaphore object, use: sem_t sem_name;
- sem_t the_semaphore;
- // mutex is an abbreviation for "mutual exclusion".
- // mutex variables are one of the primary means of implementing
- // thread synchronization and for protecting shared data when
- // multiple writes occur
- pthread_mutex_t the_mutex = PTHREAD_MUTEX_INITIALIZER;
- // server socket PF_INET
- // communication type SOCK_STREAM
- int main (int argc, const char * argv[])
- {
- int the_ns;
- struct sockaddr_in the_client_address;
- unsigned int the_client_length;
- // initialize the semaphore in the main function
- sem_init(&the_semaphore, 0, 0);
- if (argc != 2)
- {
- printf("utilizacao: %s numero_porta\n", argv[0]);
- exit(1);
- }
- // atoi: convert ASCII string to integer
- int the_socket = prepara_socket_servidor(atoi(argv[1]));
- the_client_length = sizeof(the_client_address);
- while(1)
- {
- printf("aguardar ligacao\n");
- // accept/reject jobs sent to a destination
- the_ns = accept(the_socket, (struct sockaddr *) &the_client_address, &the_client_length);
- printf("ligacao de %s\n", inet_ntoa(*((struct in_addr *) &(the_client_address.sin_addr))));
- atende_pedido(the_ns);
- }
- return 0;
- }
- int prepara_socket_servidor(int the_port)
- {
- struct sockaddr_in the_server_address;
- // create an endpoint for communication
- int the_socket = socket(PF_INET, SOCK_STREAM, 0);
- if (the_socket < 0)
- {
- perror("erro no socket");
- exit(1);
- }
- // fill a byte string with a byte value
- memset(&the_server_address, 0, sizeof(the_server_address));
- the_server_address.sin_family = AF_INET;
- the_server_address.sin_addr.s_addr = INADDR_ANY;
- the_server_address.sin_port = htons(the_port);
- if (bind(the_socket, (struct sockaddr *)&the_server_address, sizeof(the_server_address)) < 0)
- {
- perror("erro na ligacao");
- exit(1);
- }
- // listen for connections on a socket
- listen(the_socket, 5);
- return the_socket;
- }
- void *output_thread(void *the_fp)
- {
- veiculo_t v1;
- FILE *the_record = fopen(PROP, "a+");
- while(fread(&v1, sizeof(v1), 1, the_record) != 0)
- {
- if (v1.apagado == '0')
- {
- fwrite(&v1, sizeof(v1), 1, the_fp);
- }
- }
- fclose(the_record);
- fclose(the_fp);
- // prevent "the_count" changes when simultaneous connections occurs
- pthread_mutex_lock(&the_mutex);
- the_count--;
- pthread_mutex_unlock(&the_mutex);
- if ((the_count == 0) && (the_request == 1))
- {
- // increments the value of the semaphore and wakes up
- // a blocked process waiting on the semaphore, if any
- sem_post(&the_semaphore);
- the_request--;
- }
- return (NULL);
- }
- void atende_pedido(int ns)
- {
- veiculo_t v1;
- pthread_t the_tid;
- char matricula[8];
- char the_temp[8];
- FILE *the_record;
- // stream open function
- FILE *the_fp = fdopen(ns, "r+");
- if (the_fp == NULL)
- {
- perror("fdopen");
- close(ns);
- return;
- }
- // get next character or word from input stream
- char the_option = fgetc(the_fp);
- switch(the_option)
- {
- case '1':
- the_record = fopen(PROP, "a+");
- fgets(v1.proprietario, NAME_BUFFER_SIZE, the_fp);
- fgetc(the_fp);
- fgets(the_temp, 8, the_fp);
- memcpy(v1.matricula, the_temp, 6);
- v1.apagado = '0';
- if (the_count != 0)
- {
- the_request++;
- // wait on a semaphore
- sem_wait(&the_semaphore);
- }
- fwrite(&v1, sizeof(v1), 1, the_record);
- fclose(the_record);
- fclose(the_fp);
- break;
- case '2':
- // prevent "the_count" changes when simultaneous connections occurs
- pthread_mutex_lock(&the_mutex);
- the_count++;
- pthread_mutex_unlock(&the_mutex);
- pthread_create(&the_tid, NULL, output_thread, the_fp);
- pthread_detach(the_tid);
- break;
- case '3':
- the_record = fopen(PROP, "r+");
- // binary stream input/output
- fread(matricula, 8, 1, the_fp);
- apagar_registo(matricula, the_record);
- fclose(the_record);
- fclose(the_fp);
- break;
- }
- }
- //
- // main.c
- // cliente
- #include "func.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <unistd.h>
- #include <string.h>
- FILE *ligar_ao_servidor(struct hostent* the_host_info, int the_port)
- {
- // create an endpoint for communication
- int the_socket = socket(PF_INET, SOCK_STREAM, 0);
- if (the_socket < 0)
- {
- perror("erro no socket");
- return NULL;
- }
- struct sockaddr_in the_address;
- // fill a byte string with a byte value
- memset(&the_address, 0, sizeof(the_address));
- the_address.sin_family = AF_INET;
- the_address.sin_addr = *((struct in_addr *)the_host_info->h_addr);
- the_address.sin_port = htons(the_port);
- // initiate a connection on a socket
- if (connect(the_socket, (struct sockaddr *) &the_address, sizeof(struct sockaddr_in)) < 0)
- {
- perror("erro na ligacao");
- return NULL;
- }
- // stream open function
- FILE *the_fp = fdopen(the_socket, "r+");
- if (the_fp == NULL)
- {
- close(the_socket);
- }
- return the_fp;
- }
- int main (int argc, const char * argv[])
- {
- veiculo_t v1;
- char the_matricula[8];
- FILE *the_fp;
- if (argc != 3)
- {
- printf("utilizacao: %s ip_servidor numero_porta\n",argv[0]);
- exit(1);
- }
- // do it once
- struct hostent *the_host_info = gethostbyname(argv[1]);
- int the_port = atoi(argv[2]);
- int the_option;
- do
- {
- printf("\n1: inserir registo");
- printf("\n2: visualizar registos");
- printf("\n3: apagar registo");
- printf("\n\n4: sair do programa\n");
- scanf("%d", &the_option);
- getchar();
- switch(the_option)
- {
- case 1:
- ler_registo(&v1);
- the_fp = ligar_ao_servidor(the_host_info, the_port);
- fputc('1', the_fp);
- // output a line to a stream
- fputs(v1.proprietario, the_fp);
- fputc('\n', the_fp);
- fputs(v1.matricula, the_fp);
- // flush a stream
- fflush(the_fp);
- fclose(the_fp);
- break;
- case 2:
- the_fp = ligar_ao_servidor(the_host_info, the_port);
- fputc('2', the_fp);
- while(fread(&v1, sizeof(v1), 1, the_fp) !=0)
- {
- imprimir_registo(&v1);
- }
- fclose(the_fp);
- break;
- case 3:
- printf("\nmatricula: ");
- fgets(the_matricula, 8, stdin);
- the_fp = ligar_ao_servidor(the_host_info, the_port);
- fputc('3', the_fp);
- fwrite(the_matricula, 8, 1, the_fp);
- fclose(the_fp);
- break;
- case 4:
- break;
- default:
- printf("opcao invalida");
- break;
- }
- } while(the_option != 4);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement