Startpunkten
This commit is contained in:
BIN
Lab4/datafile
Normal file
BIN
Lab4/datafile
Normal file
Binary file not shown.
38
Lab4/db.h
Normal file
38
Lab4/db.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef __DB_H__
|
||||
#define __DB_H__
|
||||
|
||||
#define NAMESIZE 30
|
||||
#define NRSIZE 10
|
||||
#define ACK 0
|
||||
#define ADD 1
|
||||
#define DEL 2
|
||||
#define NR 3
|
||||
#define NAME 4
|
||||
#define EXIT 5
|
||||
#define PRN 6
|
||||
#define NACK 9
|
||||
|
||||
#define FILENAME "datafile"
|
||||
#define TMPFILE "tmpfile"
|
||||
#define READLOCK ".rlock"
|
||||
#define WRITELOCK ".wlock"
|
||||
#define PERMS 0666
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
typedef struct msg{
|
||||
int op; /* The type of operation */
|
||||
char nr[NRSIZE]; /* Telephone number */
|
||||
char name[NAMESIZE]; /* The name */
|
||||
}msg;
|
||||
|
||||
typedef msg *msgPtr;
|
||||
|
||||
#endif
|
||||
146
Lab4/dbclient.c
Normal file
146
Lab4/dbclient.c
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
#include "db.h"
|
||||
|
||||
void addNumber(msg *myMsg){
|
||||
char nr[NRSIZE], name[NAMESIZE];
|
||||
printf("ADD \n============\n");
|
||||
printf("Enter number: "); gets(nr);
|
||||
printf("Enter name: "); gets(name);
|
||||
myMsg->op = ADD;
|
||||
strcpy(myMsg->nr, nr);
|
||||
strcpy(myMsg->name, name);
|
||||
}
|
||||
|
||||
void delNumber(msg *myMsg) {
|
||||
char nr[NRSIZE];
|
||||
printf("Delete \n=============\n");
|
||||
printf("Enter number: "); gets(nr);
|
||||
myMsg->op = DEL;
|
||||
strcpy(myMsg->nr, nr);
|
||||
strcpy(myMsg->name, "");
|
||||
}
|
||||
|
||||
void findNumber(msg *myMsg) {
|
||||
char name[NAMESIZE];
|
||||
printf("Find \n=============\n");
|
||||
printf("Enter name: "); gets(name);
|
||||
myMsg->op = NR;
|
||||
strcpy(myMsg->nr, "");
|
||||
strcpy(myMsg->name, name);
|
||||
}
|
||||
|
||||
void findName(msg *myMsg) {
|
||||
char nr[NRSIZE];
|
||||
printf("Find \n=============\n");
|
||||
printf("Enter number: "); gets(nr);
|
||||
myMsg->op = NAME;
|
||||
strcpy(myMsg->nr, nr);
|
||||
strcpy(myMsg->name, "");
|
||||
}
|
||||
|
||||
void getOut(msg *myMsg, int sock) {
|
||||
printf("Quitting...\n===============\n");
|
||||
myMsg->op = EXIT;
|
||||
write(sock, myMsg, sizeof(myMsg));
|
||||
close(sock);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void printMsg(msg myMsg) {
|
||||
printf("myMsg.nr = %s\n", myMsg.nr);
|
||||
printf("myMsg.name = %s\n", myMsg.name);
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
void menu(msg *myMsg, int sock) {
|
||||
char choice[5];
|
||||
char val;
|
||||
|
||||
system("clear");
|
||||
|
||||
puts("\nWelcome to IPC, InternalPhonenumberCatalogue");
|
||||
puts("============================================\n\n");
|
||||
|
||||
puts("1 - Add a number\n");
|
||||
puts("2 - Delete a number\n");
|
||||
puts("3 - Find a number\n");
|
||||
puts("4 - Find a name\n");
|
||||
puts("5 - Exit\n\n");
|
||||
puts("Enter your choice: ");
|
||||
|
||||
fgets(choice, sizeof(choice), stdin);
|
||||
|
||||
switch(choice[0]){
|
||||
case '1': addNumber(myMsg);
|
||||
break;
|
||||
case '2': delNumber(myMsg);
|
||||
break;
|
||||
case '3': findNumber(myMsg);
|
||||
break;
|
||||
case '4': findName(myMsg);
|
||||
break;
|
||||
case '5': getOut(myMsg, sock);
|
||||
break;
|
||||
|
||||
default : puts("Try again <1-4 or 5>\n\n");
|
||||
sleep(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
char *remhost;
|
||||
u_short remport;
|
||||
int sock;
|
||||
struct sockaddr_in remote;
|
||||
struct hostent *h;
|
||||
msg myMsg;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr,"Usage: dbclient <host> <port>\n");
|
||||
exit(1);
|
||||
}
|
||||
remhost = argv[1];
|
||||
remport = atoi(argv[2]);
|
||||
|
||||
/* Create the socket. */
|
||||
if((sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
|
||||
perror("dbclient:socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bzero((char *) &remote, sizeof(remote));
|
||||
remote.sin_family = AF_INET;
|
||||
if((h = gethostbyname(remhost)) == NULL) {
|
||||
perror("dbclient:gethostbyname");
|
||||
exit(1);
|
||||
}
|
||||
bcopy((char *)h->h_addr, (char *)&remote.sin_addr, h->h_length);
|
||||
remote.sin_port = htons(remport);
|
||||
|
||||
if(connect(sock, (struct sockaddr *)&remote, sizeof(remote)) < 0) {
|
||||
perror("dbclient:connect");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
menu(&myMsg, sock);
|
||||
write(sock, &myMsg, sizeof(myMsg));
|
||||
read(sock, &myMsg, sizeof(myMsg));/*lyssna efter svar från servern*/
|
||||
|
||||
if(myMsg.op == NACK) {
|
||||
puts("Could not execute your request, please try again");
|
||||
}
|
||||
else if(myMsg.op == ACK) {
|
||||
printf("Operation executed.\n");
|
||||
}
|
||||
else if(myMsg.op == PRN) {
|
||||
printMsg(myMsg);
|
||||
}
|
||||
sleep(2);
|
||||
}
|
||||
close(sock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
247
Lab4/dbserver.c
Normal file
247
Lab4/dbserver.c
Normal file
@@ -0,0 +1,247 @@
|
||||
#include "db.h"
|
||||
|
||||
void Kill_Process() {
|
||||
kill(0, SIGTERM);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void P(char *lockfile) { /* Proberen */
|
||||
int tempfd;
|
||||
while((tempfd = creat(lockfile, 0)) < 0); /* Försök skapa låsfilen */
|
||||
close(tempfd);
|
||||
}
|
||||
|
||||
void V(char *lockfile) { /* Verhogen */
|
||||
unlink(lockfile);
|
||||
}
|
||||
|
||||
printsin(struct sockaddr_in *sin, char *m1, char *m2 ) {
|
||||
struct hostent *gethostbyaddr(), *h;
|
||||
printf ("%s %s\n", m1, m2);
|
||||
printf ("Family %d addr %x port %d\n", sin -> sin_family,
|
||||
ntohl(sin -> sin_addr.s_addr), ntohs(sin -> sin_port));
|
||||
h = gethostbyaddr((char *)&sin->sin_addr, sizeof(int), AF_INET);
|
||||
printf ("Symbolic host name <%s>\n",h->h_name);
|
||||
}
|
||||
|
||||
void doAdd(msg *myMsg) {
|
||||
int fd, i=0;
|
||||
printf("Adding %s\n", myMsg->name);
|
||||
|
||||
P(READLOCK);
|
||||
if((fd = open(FILENAME, O_CREAT|O_WRONLY|O_APPEND, PERMS)) < 0) {
|
||||
myMsg->op = NACK; /* Return error to client */
|
||||
exit(1);
|
||||
}
|
||||
write(fd, &myMsg->nr, NRSIZE);
|
||||
write(fd, &myMsg->name, NAMESIZE);
|
||||
|
||||
if((close(fd)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
V(READLOCK);
|
||||
return;
|
||||
}
|
||||
myMsg->op = ACK;
|
||||
V(READLOCK);
|
||||
}
|
||||
|
||||
void doDel(msg *myMsg) {
|
||||
int i=0, j=0, file, temp;
|
||||
struct stat st1;
|
||||
struct stat st2;
|
||||
long a, b;
|
||||
char c, nr[NRSIZE], name[NAMESIZE];
|
||||
|
||||
P(READLOCK);
|
||||
P(WRITELOCK);
|
||||
if((file = open(FILENAME, O_RDONLY)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
if((temp = open(TMPFILE, O_RDWR|O_CREAT|O_TRUNC, PERMS)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
|
||||
while(read(file, nr, NRSIZE) > 0) {
|
||||
read(file, name, NAMESIZE);
|
||||
if(strcmp(nr, myMsg->nr) != 0) {
|
||||
write(temp, nr, NRSIZE);
|
||||
write(temp, name, NAMESIZE);
|
||||
}
|
||||
}
|
||||
fstat(file, &st1);
|
||||
a = st1.st_size;
|
||||
fstat(temp, &st2);
|
||||
b = st2.st_size;
|
||||
|
||||
if((close(file)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
if((close(temp)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
if((temp = open(TMPFILE, O_RDONLY)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
if((file = open(FILENAME, O_RDWR|O_CREAT|O_TRUNC, PERMS)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
|
||||
while(read(temp, &c ,1) > 0){
|
||||
write(file, &c, 1);
|
||||
}
|
||||
if((close(file)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
if((close(temp)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
if((unlink(TMPFILE)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
V(WRITELOCK);
|
||||
V(READLOCK);
|
||||
|
||||
if(a == b) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
myMsg->op = ACK;
|
||||
}
|
||||
|
||||
void doFindNumber(msg *myMsg) {
|
||||
int file;
|
||||
char nr[NRSIZE], name[NAMESIZE];
|
||||
|
||||
P(READLOCK);
|
||||
if((file = open(FILENAME, O_RDONLY)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
|
||||
while(read(file, nr, NRSIZE) > 0){
|
||||
read(file, name, NAMESIZE);
|
||||
if(strcmp(name, myMsg->name) == 0) {
|
||||
myMsg->op = PRN;
|
||||
strcpy(myMsg->nr, nr);
|
||||
V(READLOCK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
myMsg->op = NACK;
|
||||
close(file);
|
||||
V(READLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
void doFindName(msg *myMsg) {
|
||||
int file;
|
||||
char nr[NRSIZE], name[NAMESIZE];
|
||||
|
||||
P(READLOCK);
|
||||
if((file = open(FILENAME, O_RDONLY)) < 0) {
|
||||
myMsg->op = NACK;
|
||||
return;
|
||||
}
|
||||
|
||||
while(read(file, nr, NRSIZE) > 0){
|
||||
read(file, name, NAMESIZE);
|
||||
printf("\n nr=%s, myMsg->nr=%s",nr, myMsg->nr);
|
||||
if(strcmp(nr, myMsg->nr) == 0) {
|
||||
myMsg->op = PRN;
|
||||
strcpy(myMsg->name, name);
|
||||
V(READLOCK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
close(file);
|
||||
V(READLOCK);
|
||||
myMsg->op = NACK;
|
||||
}
|
||||
|
||||
void doExit(msg *myMsg, int data_sockfd) {
|
||||
printf("Quitting...\n");
|
||||
close(data_sockfd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
main() {
|
||||
int listener, childpid, data_sockfd, status, client_length, length;
|
||||
msg myMsg;
|
||||
struct sockaddr_in srvr_addr, client_addr;
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
signal(SIGINT, Kill_Process);
|
||||
/*signal(SIGTERM, Kill_Process);*/
|
||||
|
||||
if((listener = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
|
||||
perror("server: can't open stream socket");
|
||||
exit(0);
|
||||
}
|
||||
bzero((char *) &srvr_addr, sizeof(srvr_addr));
|
||||
srvr_addr.sin_family = AF_INET;
|
||||
srvr_addr.sin_addr.s_addr = htons(INADDR_ANY);
|
||||
srvr_addr.sin_port = 27015;
|
||||
|
||||
if(bind(listener, (struct sockaddr *)&srvr_addr, sizeof(srvr_addr)) < 0) {
|
||||
perror("server: can't bind local address");
|
||||
exit(0);
|
||||
}
|
||||
/* Print out the port number assigned to this process by bind(). */
|
||||
length = sizeof(srvr_addr);
|
||||
|
||||
if(getsockname(listener, (struct sockaddr *)&srvr_addr, &length) < 0) {
|
||||
perror("server: can't get sockname");
|
||||
exit(0);
|
||||
}
|
||||
printf("Port number %d\n", ntohs(srvr_addr.sin_port));
|
||||
listen(listener,10);
|
||||
|
||||
for(;;) {
|
||||
/* Wait for a connection from a client process */
|
||||
client_length = sizeof(client_addr);
|
||||
if ((data_sockfd=accept(listener,
|
||||
(struct sockaddr *)&client_addr, &length)) < 0) {
|
||||
perror("server: accept error");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printsin(&client_addr,"\nRSTREAM", "accepted connection from");
|
||||
if((childpid = fork()) < 0) {
|
||||
perror("server: fork error");
|
||||
exit(0);
|
||||
}
|
||||
else if(childpid == 0) { /* Child process */
|
||||
close(listener);
|
||||
while(1) {
|
||||
read(data_sockfd, &myMsg, sizeof(myMsg));
|
||||
|
||||
switch(myMsg.op) {
|
||||
case 1: doAdd(&myMsg);
|
||||
write(data_sockfd, &myMsg, sizeof(myMsg));
|
||||
break;
|
||||
case 2: doDel(&myMsg);
|
||||
write(data_sockfd, &myMsg, sizeof(myMsg));
|
||||
break;
|
||||
case 3: doFindNumber(&myMsg);
|
||||
write(data_sockfd, &myMsg, sizeof(myMsg));
|
||||
break;
|
||||
case 4: doFindName(&myMsg);
|
||||
write(data_sockfd, &myMsg, sizeof(myMsg));
|
||||
break;
|
||||
case 5: doExit(&myMsg, data_sockfd);
|
||||
|
||||
default: break;
|
||||
}
|
||||
myMsg.op = ACK; /* töm struktens op så den inte är kvar till switchen */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Lab4/read_me
Normal file
10
Lab4/read_me
Normal file
@@ -0,0 +1,10 @@
|
||||
Laboration 4 i C & UNIX
|
||||
========================================
|
||||
Databas med klient & server
|
||||
Starta servern, sedan klienten
|
||||
med portnumret du fick.
|
||||
|
||||
Labben är provkörd och klar.
|
||||
========================================
|
||||
Christian Ohlsson, di7chro@cse.kau.se
|
||||
|
||||
Reference in New Issue
Block a user