Startpunkten

This commit is contained in:
2026-03-05 13:31:50 +01:00
commit 86a20ae0e1
16 changed files with 1305 additions and 0 deletions

BIN
Lab4/datafile Normal file

Binary file not shown.

38
Lab4/db.h Normal file
View 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
View 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
View 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
View 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