commit fd04d44e1225adfdce446a340ad74b2424de2564 Author: Christian Ohlsson Date: Thu Mar 5 13:35:06 2026 +0100 Startpunkten diff --git a/c_app.c b/c_app.c new file mode 100644 index 0000000..63f2149 --- /dev/null +++ b/c_app.c @@ -0,0 +1,45 @@ +/* ***************************************** */ +/* Laboration 2 i Datakommunikation 2 */ +/* RPC-lib */ +/* ***************************************** */ +/* c_app.c */ +/* Ber användaren mata in vilken typ */ +/* av operation denne vill göra */ +/* ***************************************** */ +/* Christian Ohlsson, di7chro@cse.kau.se */ +/* Stefan Sonesson, di7stes@cse.kau.se */ +/* ***************************************** */ +#include "header.h" + +/* ============================================== + menu() + Skriver ut menyn på skärmen + ============================================== */ +int menu() { + char choice[5]; + int ret_val = TRUE; + system("clear"); + puts("Welcome to RPC"); + puts("================"); + puts("1 - Open file"); + puts("2 - Read file"); + puts("3 - Write to file"); + puts("4 - Delete file"); + puts("5 - Close file"); + puts("6 - Exit"); + + printf("\nEnter your choice: "); + fgets(choice, sizeof(choice), stdin); + + switch(choice[0]){ + case '1': ret_val = in_open(); break; + case '2': ret_val = in_read(); break; + case '3': ret_val = in_write(); break; + case '4': ret_val = in_delete(); break; + case '5': ret_val = in_close(); break; + case '6': ret_val = in_quit(); break; + default : puts("Try again 1-5 or 6");break; + } + return ret_val; +} + diff --git a/c_stub.c b/c_stub.c new file mode 100644 index 0000000..48506ba --- /dev/null +++ b/c_stub.c @@ -0,0 +1,259 @@ +/* ***************************************** */ +/* Laboration 2 i Datakommunikation 2 */ +/* RPC-lib */ +/* ***************************************** */ +/* c_stub.c */ +/* Klientapplikation som skickar */ +/* kommandon till servern */ +/* ***************************************** */ +/* Christian Ohlsson, di7chro@cse.kau.se */ +/* Stefan Sonesson, di7stes@cse.kau.se */ +/* ***************************************** */ + +#include "header.h" + +/* Globala variabler */ +int fd=-1, sock; /* fd kommer ihåg om någon fil är öppen */ +msg myMsg; /* Meddelandet som funktionerna fyller i */ + +/* ============================================== + in_connect() + Gör en uppkoppling mot en server + ============================================== */ +void in_connect() { + char *remhost; + u_short remport; + struct sockaddr_in remote; + struct hostent *h; + /* Skapa en socket att skicka data på */ + if((sock = socket(AF_INET, SOCK_STREAM, 0 )) < 0 ) { + perror("client:socket"); + exit(1); + } + remport = 8704; + /* Nolla ut structen */ + bzero((char *) &remote, sizeof(remote)); + remote.sin_family = AF_INET; + /* Fyll i hostent structen */ + if((h = gethostbyname(myMsg.machine)) == NULL) { + perror("client:gethostbyname"); + exit(1); + } + bcopy((char *)h->h_addr, (char *)&remote.sin_addr, h->h_length); + remote.sin_port = htons(remport); + /* Begär uppkoppling mot servern */ + if(connect(sock, (struct sockaddr *)&remote, sizeof(remote)) < 0) { + perror("client:connect"); + exit(1); + } +} + +/* ============================================== + in_open() + Letar fram server och fil att öppna + ============================================== */ +int in_open() { + int i,j,k=0; + char this_machine[BUFSIZE], this_path[BUFSIZE], filename[BUFSIZE]; + if(fd<0) { + printf("Enter filename: "); + fgets(filename, sizeof(filename), stdin); + for(i = 0; i < BUFSIZE; i++) { + if(filename[i] != '/') + this_machine[i] = filename[i]; + else { + this_machine[i] = 0; + break; + } + } + for(; i < BUFSIZE ; i++) { + if(filename[i] != 10) { + this_path[k] = filename[i]; + k++; + } + else { + this_path[k] = 0; + break; + } + } + myMsg.op = OP; + if(filename[0] == '/') /* Lokal fil */ + strcpy(this_machine, "localhost"); + strcpy(myMsg.machine, this_machine); + strcpy(myMsg.path, this_path); + in_connect(myMsg); + } + else { + puts("A file is already open!"); + sleep(SLEEPTIME); + return FALSE; + } + return TRUE; +} + +/* ============================================== + in_read() + Sätter operatorn till READ + ============================================== */ +int in_read() { + if(fd > 0) + myMsg.op = RD; + else { + puts("No file is open!"); + sleep(SLEEPTIME); + return FALSE; + } + return TRUE; +} + +/* ============================================== + in_write() + Frågar hur mycket som skall skrivas och + sätter operatorn + ============================================== */ +int in_write() { + char buf[BUFSIZE]; + int length = 0; + if(fd>0) { + printf("How many bytes do you wish to write: "); + gets(buf); + length = atoi(buf); + printf("Enter text: "); + if((myMsg.data = (char*)malloc(length)) < 0) { + perror("Malloc fel, byt minnesskretsarna, eller skaffa fler\n"); + return FALSE; + } + myMsg.length = length; + gets(myMsg.data); + myMsg.op = WR; + } + else { + puts("No file is open!"); + sleep(SLEEPTIME); + return FALSE; + } + return TRUE; +} + +/* ============================================== + in_delete() + Sätter operatorn till DELETE + ============================================== */ +int in_delete() { + if(fd > 0) + myMsg.op = DEL; + else { + puts("No file is open!"); + sleep(SLEEPTIME); + return FALSE; + } + return TRUE; +} + +/* ============================================== + + in_close() + Sätter operatorn till CLOSE + ============================================== */ +int in_close() { + if(fd > 0) + myMsg.op = CL; + else { + puts("No file is open!"); + sleep(SLEEPTIME); + return FALSE; + } + return TRUE; +} + +/* ============================================== + showFile() + Om data finns i filen skrivs detta ut + ============================================== */ +void showFile(char *data) { + if(myMsg.length > 0) + printf("Data:%s\n",data); + else + puts("File contains no data."); + sleep(SLEEPTIME); +} + +/* ============================================== + in_quit() + Stänger socketen och avslutar + ============================================== */ +int in_quit() { + if(fd > 0) { + puts("Close file first."); + sleep(SLEEPTIME); + return FALSE; + } + else { + puts("QUIT"); + close(sock); + exit(0); + } +} +void in_exit() { + close(sock); + puts("Application error, probably due to underpaid programmers"); + exit(0); +} + +/* ============================================== + main() + Anropar funktioner beroende på menyval + ============================================== */ +main() { + char *data; + signal(SIGCHLD, SIG_IGN); + signal(SIGINT, SIG_IGN); + + while(TRUE) { + if(menu(myMsg)) { + if((write(sock, &myMsg, sizeof(myMsg))) < 0) + {puts("1");in_exit();} + write(sock, myMsg.data, myMsg.length); + if((read(sock, &myMsg, sizeof(myMsg))) < 0) /*lyssna efter svar från servern*/ + {puts("3");in_exit();} + switch(myMsg.op) { + case OPN: /* Öppning misslyckades */ + puts("Could not open file."); + sleep(SLEEPTIME); break; + case OPP: /* Öppning gick bra */ + printf("File: %s is open", myMsg.path);fflush(stdout); + fd = myMsg.fd;sleep(SLEEPTIME); break; + case RDN: /* Läsning misslyckades */ + puts("Could not read from file."); + sleep(SLEEPTIME); break; + case RDP: /* Läsning gick bra */ + if((data = (char*)malloc(myMsg.length)) == NULL) { + puts("Could not read from file.");break;} + if((read(sock, data, myMsg.length)) < 0) { + puts("Could not read from file");break;} + showFile(data);break; + case WRN: /* Skrivning misslyckades */ + puts("Could not write to file."); + sleep(SLEEPTIME);break; + case WRP: /* Skrivning gick bra */ + printf("%d bytes written.\n", myMsg.length); + sleep(SLEEPTIME);break; + case DLN: /* Borttagning misslyckades */ + puts("Could not delete file."); + sleep(SLEEPTIME);break; + case DLP: /* Borttagning gick bra */ + printf("File %s deleted\n", myMsg.path); + fd=-1; sleep(SLEEPTIME);break; + case CLN: /* Stängning misslyckades */ + puts("Could not close file."); + sleep(SLEEPTIME);break; + case CLP: /* Stängning gick bra */ + printf("File: %s is closed\n", myMsg.path); + fd=-1;sleep(SLEEPTIME);close(sock);break; + default: puts(".");sleep(SLEEPTIME);break; + } + } + } + /*close(sock);*/ +} + diff --git a/c_stub.o b/c_stub.o new file mode 100644 index 0000000..e96bb1d Binary files /dev/null and b/c_stub.o differ diff --git a/header.h b/header.h new file mode 100644 index 0000000..1e73ae9 --- /dev/null +++ b/header.h @@ -0,0 +1,63 @@ +/* ***************************************** */ +/* Laboration 2 i Datakommunikation 2 */ +/* RPC-lib */ +/* ***************************************** */ +/* header.h */ +/* Innehåller deklarationer och konstanter */ +/* ***************************************** */ +/* Christian Ohlsson, di7chro@cse.kau.se */ +/* Stefan Sonesson, di7stes@cse.kau.se */ +/* ***************************************** */ +#ifndef __HEADER_H__ +#define __HEADER_H__ + +/* Kommandon som kan skickas */ +#define OP 0 +#define OPP 1 +#define OPN 2 +#define RD 3 +#define RDP 4 +#define RDN 5 +#define WR 6 +#define WRP 7 +#define WRN 8 +#define DEL 9 +#define DLP 10 +#define DLN 11 +#define CL 12 +#define CLP 13 +#define CLN 14 + +/* Konstanter */ +#define BUFSIZE 50/* Buffertstorlek vid inmatning */ +#define MAXCONNECTED 1 /* Antal samtidiga användare */ +#define SLEEPTIME 2 /* Sov-tid vid utskrifter */ +#define TRUE 1 /* Boolsk variabel */ +#define FALSE 0 /* Boolsk variabel */ +#define PERMS 0666 /* Rättigheter på nya filer */ +#define PORT 34 /* Port som trafiken går mot */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Meddelande som skickas över */ +typedef struct msg{ + int op; /* Typ av kommando */ + int fd; /* Fildeskriptor */ + long length; /* Storlek på data */ + char machine[50]; /* Maskin vi vill koppla upp mot */ + char path[50]; /* Sökväg på maskinen */ + char *data; /* Datafält */ +}msg; + +typedef msg *msgPtr; + +#endif + diff --git a/read_me b/read_me new file mode 100644 index 0000000..17ee7e7 --- /dev/null +++ b/read_me @@ -0,0 +1,15 @@ +Readmefil för Laboration i +Datakommunikation II +================================= + + RPC-lib + + Kompilera genom att köra + makefilen (make) + .SDR filerna i Doc/ katalogen + är skapade med SmartDraw + Labben är provkörd och klar. + +================================ + Christian.Ohlsson@cs.kau.se + diff --git a/s_stub.c b/s_stub.c new file mode 100644 index 0000000..b4fcd20 --- /dev/null +++ b/s_stub.c @@ -0,0 +1,213 @@ +/* ***************************************** */ +/* Laboration 2 i Datakommunikation 2 */ +/* RPC-lib */ +/* ***************************************** */ +/* s_stub.c */ +/* Ansvarar för att operationer utförs */ +/* utförs på rätt sätt i servern */ +/* ***************************************** */ +/* Christian Ohlsson, di7chro@cse.kau.se */ +/* Stefan Sonesson, di7stes@cse.kau.se */ +/* ***************************************** */ + +#include "header.h" + +/* Globala variabler */ +int data_sockfd; /* Den socket som data färdas på */ +msg myMsg; /* Meddelandet som funktionerna fyller i */ + +/* ============================================== + printsin() + Skriver ut information om klienten + ============================================== */ +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); +} + +/* ============================================== + rem_open() + Öppnar en fil och fyller i data såsom + längd och fildeskriptor i strukten. + ============================================== */ +void rem_open() { + int fd; + struct stat st; + if((fd = open(myMsg.path, O_CREAT|O_RDWR|O_APPEND, PERMS)) < 0) { + myMsg.op = OPN; /* Skicka fel till klient */ + return; + } + fstat(fd, &st); + myMsg.length = st.st_size; + myMsg.op = OPP; /* Operationen gick bra */ + myMsg.fd = fd; +} + +/* ============================================== + rem_read() + Läser data ur en fil tills EOF tecknet nås och + dessa tecken stoppas i en buffer, som slutligen + returneras + ============================================== */ +char *rem_read() { + char *buf; + int fd; + lseek(myMsg.fd, 0, SEEK_SET); + buf = (char*)malloc(myMsg.length); + + if((read(myMsg.fd, buf, myMsg.length)) < 0) + myMsg.op = RDN; /* Skicka fel till klient */ + else + myMsg.op = RDP; /* Operationen gick bra */ + return buf; +} + +/* ============================================== + rem_write() + Skriver tecken till fil + ============================================== */ +void rem_write() { + if((write(myMsg.fd, myMsg.data, myMsg.length)) < 0) + myMsg.op = WRN; /* Skicka fel till klient */ + else + myMsg.op = WRP; /* Operationen gick bra */ +} +/* ============================================== + rem_delete() + Tar bort en fil mha unlink, som egentligen + räknar ner antalet länkar till en fil + ============================================== */ +int rem_delete() { + if((unlink(myMsg.path)) < 0) { + myMsg.op = DLN; /* Skicka fel till klient */ + return 0; + } + else { + myMsg.op = DLP; /* Operationen gick bra */ + return 1; + } +} + +/* ============================================== + rem_close() + Stänger en fil. + Returnerar svar om hur det gick + ============================================== */ +int rem_close() { + if((close(myMsg.fd)) < 0) { + myMsg.op = CLN; /* Skicka fel till klient */ + return 0; + } + else { + myMsg.op = CLP; /* Operationen gick bra */ + return 1; + } +} +/* ============================================== + rem_exit() + Stänger datasocketen vid fel. + Avslutar programmet + ============================================== */ +void rem_exit() { + puts("Quitting"); + close(data_sockfd); + exit(0); +} +/* ============================================== + main() + Sköter uppkoppling och lyssnar efter klienter + ============================================== */ +main() { + int listener, client_length, length, val, again; + char *bytes; + struct sockaddr_in srvr_addr, client_addr; + signal(SIGCHLD, SIG_IGN); + signal(SIGINT, rem_exit); + + /* Skapa en socket som lyssnar efter uppkopplingar */ + if((listener = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) { + perror("server: can't open stream socket"); + exit(0); + } + /* Nolla ut strukten */ + 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 = PORT; + /* Bind ett namn till socketen */ + if(bind(listener, (struct sockaddr *)&srvr_addr, sizeof(srvr_addr)) < 0) { + perror("server: can't bind local address"); + exit(0); + } + length = sizeof(srvr_addr); + while(TRUE) { + /* Hämta namnet på socketen */ + 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)); + /* Lyssna efter uppkopplingar */ + listen(listener, MAXCONNECTED); + + client_length = sizeof(client_addr); + /* Acceptera den nya uppkopplingen */ + if ((data_sockfd=accept(listener, + (struct sockaddr *)&client_addr, &length)) < 0) { + perror("server: accept error"); + exit(0); + } + /*printsin(&client_addr,"\nRSTREAM", "accepted connection from");*/ + again=1; + while(again) { + /* Läs data från socketen */ + if((read(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + + switch(myMsg.op) { + case OP: /* Klienten vill öppna en fil */ + rem_open(); + if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + break; + case RD: /* Klienten vill läsa från en fil */ + bytes = rem_read(); + if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + if((write(data_sockfd, bytes, myMsg.length)) < 0) + rem_exit(); + break; + case WR: /* Klienten vill skriva till en fil */ + if((myMsg.data = (char*)malloc(myMsg.length)) == NULL) { + myMsg.op = WRN; /* Om minne inte kunde allokeras */ + if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + } + if((read(data_sockfd, myMsg.data, myMsg.length)) < 0) + rem_exit(); + rem_write(); + if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + free(myMsg.data); + break; + case DEL:/* Klienten vill ta bort en fil */ + val = rem_delete(); + if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + if(val == 1) { close(data_sockfd); again=0; } + break; + case CL: /* Klienten vill stänga en fil */ + val = rem_close(); + if((write(data_sockfd, &myMsg, sizeof(myMsg))) < 0) + rem_exit(); + if(val == 1) { close(data_sockfd); again=0; } + break; + default: break; + } + } + } +} diff --git a/s_stub.o b/s_stub.o new file mode 100644 index 0000000..6c1c029 Binary files /dev/null and b/s_stub.o differ