-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.c
More file actions
231 lines (201 loc) · 7.81 KB
/
server.c
File metadata and controls
231 lines (201 loc) · 7.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <unistd.h>
/* definicja rozmiarow danych zgodna z klientem */
#define MAX_USERNAME_LENGTH 32
#define MAX_TWEET_LENGTH 128
/* struktura pamieci dzielonej */
void *shared_memory; /* adres na poczatek pamieci dzielonej */
int *shared_max_tweets; /* maksymalna liczba tweetow w pamieci wspoldzielonej */
int *shared_num_of_tweets; /* liczba tweetow w pamieci wpoldzielonej */
struct tweet { /* struktura tweeta */
char username[MAX_USERNAME_LENGTH];
char content[MAX_TWEET_LENGTH];
int likes;
} *shared_tweets;
/* zmienne globalne */
int shmid; /* id segmentu pamieci dzielonej */
int semid; /* id tablicy semaforow */
int max_tweets; /* maksymalna liczba tweetow */
void signal_handlers_init(); /* ustawienie obslugi sygnalow */
void sgnhandle(int signal); /* obsluga sygnalow */
void shared_memory_init(char *filename); /* utworzenie i dolaczenie segmentu pamieci dzielonej */
void semaphore_array_init(char *filename); /* utworzenie i inicjalizacja tablicy semaforow */
void sem_wait(int sem_num); /* opuszczenie semafora */
void sem_signal(int sem_num); /* podniesienie semafora */
void run_server(); /* glowna petla programu */
void print_tweets(); /* wypisanie tweetow */
void cleanup(); /* wyczyszczenie pamieci i usuniecie tablicy semaforow */
int main(int argc, char *argv[]) {
if (argc != 3) { /* sprawdzenie liczby argumentow */
printf("[Serwer]: Error: Wymagane 3 argumenty\n");
exit(EXIT_FAILURE);
}
max_tweets = atoi(argv[2]); /* konwersja argumentu na liczbe */
if (max_tweets < 1) { /* sprawdzenie czy liczba tweetow jest dodatnia */
printf("[Serwer]: Error: Wymagana dodatnia liczba tweetow\n");
exit(EXIT_FAILURE);
}
printf("[Serwer]: Twitter 2.0 (wersja A)\n");
signal_handlers_init();
shared_memory_init(argv[1]);
semaphore_array_init(argv[1]);
printf("[Serwer]: nacisnij CTRL^Z by wyswietlic stan serwisu\n");
printf("[Serwer]: nacisnij CTRL^C by zakonczyc program\n");
run_server();
}
/* ustawienie obslugi sygnalow */
void signal_handlers_init() {
if (signal(SIGINT, sgnhandle) == SIG_ERR) {
printf("[Serwer]: Error: %m\n");
exit(EXIT_FAILURE);
}
if (signal(SIGTSTP, sgnhandle) == SIG_ERR) {
printf("[Serwer]: Error: %m\n");
exit(EXIT_FAILURE);
}
}
/* utworzenie i dolaczenie segmentu pamieci dzielonej */
void shared_memory_init(char *filename) {
key_t shmkey;
size_t shared_data_size;
printf("[Serwer]: tworze klucz na podstawie pliku %s... ", filename);
if ((shmkey = ftok(filename, 1)) == -1) {
printf("Error: %m\n");
exit(EXIT_FAILURE);
}
printf("OK (klucz: %d)\n", (int)shmkey);
printf("[Serwer]: tworze segment pamieci wspolnej na %d wpisow po %db... ", max_tweets, MAX_TWEET_LENGTH);
/* wyznacznie rozmiaru pamieci dzielonej */
shared_data_size = sizeof(struct tweet) * max_tweets + sizeof(int) * 2;
if ((shmid = shmget(shmkey, shared_data_size, 0600 | IPC_CREAT | IPC_EXCL)) == -1) {
printf("Error: %m\n");
exit(EXIT_FAILURE);
}
/* rzutowanie ze wzgledu na inna definicje size_t na FreeBSD */
printf("OK (id: %d, rozmiar: %ldb)\n", shmid, (unsigned long)(shared_data_size));
printf("[Serwer]: dolaczam pamiec wspolna... ");
/* dolaczenie pamieci */
if ((shared_memory = shmat(shmid, NULL, 0)) == (void *)-1) {
printf("Error shmat(): %m\n");
if (shmctl(shmid, IPC_RMID, 0) == -1) { /* proba usuniecia segmentu pamieci dzielonej w przypadku bledu dolaczenia*/
printf("Error shmctl(): %m\n");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
printf("OK (adres: %lX)\n", (long int)shared_memory);
/* przypisanie wskaznikow na poszczegolne elementy pamieci dzielonej */
shared_max_tweets = (int *)(shared_memory); /* przypisanie wskaznika na maksymalna liczbe tweetow */
shared_num_of_tweets = (int *)(shared_max_tweets + 1); /* przypisanie wskaznika na aktualna liczbe tweetow */
shared_tweets = (struct tweet *)(shared_num_of_tweets + 1); /* przypisanie wskaznika na tablice tweetow */
/* przypisanie wartosci poczatkowych */
*shared_num_of_tweets = 0; /* przypisanie liczby tweetow */
*shared_max_tweets = max_tweets; /* przypisanie maksymalnej liczby tweetow */
}
/* utworzenie i inicjalizacja tablicy semaforow */
void semaphore_array_init(char *filename) {
key_t semkey;
printf("[Serwer]: tworze semafory... ");
if ((semkey = ftok(filename, 2)) == -1) {
printf("Error: %m\n");
exit(EXIT_FAILURE);
}
/* stworzenie tablicy semaforow, po jednym na kazdego slota + jeden na zmienna shared_num_of_tweets */
if ((semid = semget(semkey, max_tweets + 1, 0600 | IPC_CREAT | IPC_EXCL)) == -1) {
printf("Error: %m\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < max_tweets + 1; i++) {
if (semctl(semid, i, SETVAL, 1) == -1) {
perror("Error semctl");
exit(EXIT_FAILURE);
}
}
printf("OK (id: %d)\n", semid);
}
/* glowna petla programu*/
void run_server() {
while (1) {
sleep(1);
}
}
/* wyczyszczenie pamieci i usuniecie tablicy semaforow */
void cleanup() {
if (shmdt(shared_memory) == -1) { /* odlaczenie pamieci dzielonej */
printf("Error shmdt(): %m\n");
exit(EXIT_FAILURE);
}
printf("[Serwer]: odlaczenie pamieci: OK\n");
if (shmctl(shmid, IPC_RMID, 0) == -1) { /* usuniecie segmentu pamieci dzielonej */
printf("Error shmctl(): %m\n");
exit(EXIT_FAILURE);
}
printf("[Serwer]: usuniecie pamieci: OK\n");
if (semctl(semid, 0, IPC_RMID) == -1) { /* usuniecie tablicy semaforow */
printf("Error semctl(): %m\n");
exit(EXIT_FAILURE);
}
printf("[Serwer]: usuniecie semaforow: OK\n");
}
/* wypisanie tweetow */
void print_tweets() {
if (*shared_num_of_tweets == 0) { /* jesli nie ma zadnych wpisow to wypisujemy komunikat */
printf("\nBrak wpisow\n");
} else { /* jesli sa jakies wpisy to je wypisujemy */
printf("\n___________ Twitter 2.0: ___________\n");
/* semafory sa podnoszone i opuszczane w funkcji sgnhandle() */
for (int i = 0; i < *shared_num_of_tweets; i++) {
if (strlen(shared_tweets[i].username) != 0) {
printf("[%s]: %s [Polubienia: %d]\n", shared_tweets[i].username,
shared_tweets[i].content,
shared_tweets[i].likes);
} else {
printf("Uzytkownik wprowadza tresc...\n");
}
}
}
}
/* obsluga sygnalow */
void sgnhandle(int signal) {
if (signal == SIGINT) {
printf("\n[Serwer]: dostalem SIGINT => koncze i sprzatam...\n");
cleanup();
exit(EXIT_SUCCESS);
}
if (signal == SIGTSTP) {
for (int i = 0; i < max_tweets + 1; i++) { /* opuszczenie wszystkich semaforow */
sem_wait(i);
}
print_tweets();
for (int i = 0; i < max_tweets + 1; i++) { /* podniesienie wszystkich semaforow */
sem_signal(i);
}
}
}
/* opuszczenie semafora */
void sem_wait(int sem_num) {
struct sembuf sb;
sb.sem_num = sem_num;
sb.sem_op = -1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
printf("Error semop(): %m\n");
exit(EXIT_FAILURE);
}
}
/* podniesienie semafora */
void sem_signal(int sem_num) {
struct sembuf sb;
sb.sem_num = sem_num;
sb.sem_op = 1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
printf("Error semop(): %m\n");
exit(EXIT_FAILURE);
}
}