#define SERWER "/tmp/SERWER_SOCKET.sock"
int network_socket = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un serwer;
serwer.sun_family = AF_UNIX;
strcpy(serwer.sun_path, SERWER);
//otwieranie okna dla klienta
int socc_bind = bind(network_socket, (struct sockaddr *)&serwer, sizeof(serwer));
printf("Nie udalo sie przylaczyc do socketu\n");
int nasluchiwanie = listen(network_socket, 5);
printf("Blad nasluchiwania\n");
// int klient = accept(network_socket, NULL, NULL);
// int czytaj = read(klient, &liczba, sizeof(liczba));
// if(czytaj == sizeof(liczba)){
// int wynik = liczba * liczba;
// int wyslij = write(klient, &wynik, sizeof(wynik));
int klient = accept(network_socket, NULL, NULL);
int czytaj = read(klient, wiadomosc, sizeof(wiadomosc));
printf("Serwer otrzymal slowo: %s\n", wiadomosc);
char slowo1[256] = " siema";
strcat(slowo1, wiadomosc);
printf("Slowo po zlepieniu: %s\n: ", slowo1);
write(klient, slowo1, strlen(slowo1) + 1);
#define SERWER "/tmp/SERWER_SOCKET.sock"
int network_socket = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un serwer;
serwer.sun_family = AF_UNIX;
strcpy(serwer.sun_path, SERWER);
int soc_connect = connect(network_socket, (struct sockaddr *)&serwer, sizeof(serwer));
printf("Nie udalo sie polaczyc z serwerem\n");
write(network_socket, slowo, strlen(slowo) + 1);
read(network_socket, slowo, sizeof(slowo));
printf("Otrzymalem od serwera wiadomosc: %s\n", slowo);
//to byl gniazdowy unixowy
#define SERWER "/tmp/SOCKET-SERWER.sock"
#define KLIENT "/tmp/SOCKET-KLIENT.sock"
// interfejs serwera gniazdowego
struct sockaddr_un serwer;
struct sockaddr_un klient;
socklen_t serwer_len = sizeof(serwer);
// stworzenie gniazda datagramowego
int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
// na wszelki usuwamy istniejacy socket klienta (jak jest)
// adres klienta (musi miec wlasny!)
klient.sun_family = AF_UNIX;
strcpy(klient.sun_path, KLIENT);
// przypinamy gniazdo klienta
int soc_bind = bind(sock, (struct sockaddr *)&klient, sizeof(klient));
fprintf("Blad przypiecia");
serwer.sun_family = AF_UNIX;
strcpy(serwer.sun_path, SERWER);
printf("Podaj liczbe: ");
// wysylamy liczbe do serwera
sendto(sock, &liczba, sizeof(int), 0,
(struct sockaddr *)&serwer, serwer_len);
// czekamy na odpowiedz serwera
recvfrom(sock, &wynik, sizeof(int), 0, NULL, NULL);
printf("Wynik: %d * %d = %d\n", liczba, liczba, wynik);
// Serwer sekwencyjny uzywajacy gniazd datagramowych, ale lokalnie
// Wysyla pakiety datagramowe bez tworzenia polaczenia (dlatego nie ma listen i accept)
#define SERWER "/tmp/SOCKET-SERWER.sock"
// inicjalizujemy adresy serwera i klienta
struct sockaddr_un serwer;
struct sockaddr_un klient;
socklen_t klient_len = sizeof(klient);
// stworzenie gniazda datagramowego
// (zamiast SOCK_STREAM to SOCK_DGRAM)
// AF_UNIX - komunikacja lokalna (ale datagramami)
int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
// na wszelki usuwamy istniejacy socket serwera (jak jest)
// AF_UNIX - komunikacja lokalna (ale datagramami)
serwer.sun_family = AF_UNIX;
// skopiowanie sciezki do serwera
strcpy(serwer.sun_path, SERWER);
// przypiecie gniazda do adresu
// bind zwraca -1 jak bedzie blad
if (bind(sock, (struct sockaddr *)&serwer, sizeof(serwer)) == -1) {
printf("Serwer gniazdowy uruchomiony...\n");
// czekamy na liczbe od klienta
// nie ma listen i accept
// recvfrom = read, sendto = write
(struct sockaddr *)&klient,
&klient_len) == sizeof(liczba)) {
int wynik = liczba * liczba;
printf("dostalem liczbe, wysylam\n");
(struct sockaddr *)&klient,
// tutaj mozna wyslac kolejny datagram od klienta
Serwer sekwencyjny oparty na kolejkach komunikatów.
Kazdy komunikat musi byc wczesniej zdefiniowany jako struktura zaczynajaca
sie polem long mtype, ktore sluzy do "filtrowania" wiadomosci przez msgrcv()
w polu msgtyp i jego wartosci to:
1 - zgloszenie klienta do serwera
2 - dane wysylane przez klienta
3 - wynik wyslany przez serwer
char sciezka = "/tmp/serwer.ipc"; // musi byc char
// usun istniejacy plik serwera (na wszelki)
int plik = open(sciezka, O_CREAT);
perror("Serwer: Blad utworzenia pliku");
// tworzymy klucz kolejki dla serwera
key_t klucz_serwera = klucz_serwera = ftok(sciezka, 0);
if (klucz_serwera == -1) {
// tworzenie kolejki serwera z uprawnieniami 0600
int kolejka_serwera = msgget(klucz_serwera, IPC_CREAT | 0600);
if (kolejka_serwera == -1) {
perror("Serwer: msgget");
printf("Serwer sekwencyjny uruchomiony.\n");
// odbior zgloszenia klienta (mtype = 1)
// po to robimy strukture paczek
ssize_t liczba_bajtow = msgrcv(kolejka_serwera, &handshake, sizeof(paczka1) - sizeof(long), 1, 0);
if (liczba_bajtow == -1) {
perror("Serwer: msgrcv (glowna kolejka)");
// tworzymy klucz klienta uzywajac PID klienta jako ID projektu
if (klucz_klienta == -1) {
perror("Serwer: ftok pid");
// otwieramy kolejke klienta
int kolejka_klienta = msgget(klucz_klienta, 0600);
if (kolejka_klienta == -1) {
perror("Serwer: msgget klienta");
// odbieramy dane od klienta (mtype = 2)
liczba_bajtow = msgrcv(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 2, 0);
if (liczba_bajtow == -1) {
perror("Serwer: msgrcv klient");
printf("Serwer: otrzymano %d\n", pakiet.liczba);
// przetwarzamy liczbe w tym pakiecie i nadajemy mtype 3 (do odeslania)
pakiet.liczba *= pakiet.liczba;
// odsylamy wynik jako ten sam pakiet
if (msgsnd(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 0) == -1) {
perror("Serwer: msgsnd");
printf("Serwer: wynik odeslany\n");
Klient dla serwera sekwencyjnego opartego na kolejkach komunikatów.
praktycznie to samo co w serwerze, ale tutaj nie tworzymy serwera,
laczymy sie do niego, tworzymy kolejke klienta i wysylamy najpierw PID
przez kolejke serwera a potem liczbe przez kolejke klienta i czekamy na
char sciezka = "/tmp/serwer.ipc"; // musi byc char
pid_t pid = getpid(); // PID tego klienta
key_t klucz_serwera = ftok(sciezka, 0);
if (klucz_serwera == -1) {
int kolejka_serwera = msgget(klucz_serwera, 0600);
if (kolejka_serwera == -1) {
perror("Klient: msgget (serwer)");
key_t klucz_klienta = ftok(sciezka, pid);
if (klucz_klienta == -1) {
perror("Klient: ftok klient");
int kolejka_klienta = msgget(klucz_klienta, 0600 | IPC_CREAT);
if (kolejka_klienta == -1) {
perror("Klient: msgget (klient)");
/* Zgłoszenie do serwera */
if (msgsnd(kolejka_serwera, &handshake, sizeof(paczka1) - sizeof(long), 0) == -1) {
perror("Klient: msgsnd");
/* Dane do przetworzenia */
printf("Klient: Podaj liczbe: ");
scanf("%d", &pakiet.liczba);
if (msgsnd(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 0) == -1) {
perror("Klient: msgsnd (dane)");
msgctl(kolejka_klienta, IPC_RMID, NULL);
if (msgrcv(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 3, 0) == -1) {
perror("Klient: msgrcv");
msgctl(kolejka_klienta, IPC_RMID, NULL);
printf("Klient: Wynik = %d\n", pakiet.liczba);
Serwer sekwencyjny oparty na kolejkach FIFO
Obsluguje jednego klienta na raz ktory wysyla najpierw PID, potem liczbe calkowita,
potem serwer przetwarza ta liczbe i wysyla wynik z powrotem do klienta
2 (pisze) -----> 1 (czyta)
1 (czyta) <----- 2 (pisze)
FIFO - jednokierunkowy strumien w ktory wrzuca sie dane i nie ma jak sprawdzic czy dotarly
deskryptor - alias numeryczny do pliku
1. tworzymy ogarnianie ctrl+c i kill (signal)
2. na wszelki zamykamy stary serwer
3. tworzymy kolejke serwerowa
4. czekamy na PID od klienta
5. tworzymy kolejke do czytania i pisania
6. czekamy na liczbe i wysylamy wynik klientowi
const char *nazwa_serwera = "/tmp/FIFO-SERWER";
char bufor[256]; // bufor na nazwy klienta
void sigint_handler(int sig) {
printf("\nSerwer: zamykanie...\n");
close(deskryptor_serwera);
int kolejka_czytania, kolejka_pisania; // deskryptory kolejek FIFO
// zamkniecie starego serwera (na wszelki)
// tworzenie kolejki FIFO o nazwie 'FIFO-SERWER' z prawami dostepu tylko wlasciciela (0600),
// mknod zwaraca -1 przy bledzie
if (mknod(nazwa_serwera, S_IFIFO | 0600, 0) == -1) {
perror("Serwer: blad tworzenia kolejki FIFO");
// probujemy otworzyc serwer jako tylko do czytania w trybie blokowanym,
// co oznacza ze serwer jest zablokowany do czasu az klient otworzy FIFO
// do zapisu (w kliencie jest taka sama linijka tylko z O_WRONLY),
deskryptor_serwera = open(nazwa_serwera, O_RDONLY);
// open zwaraca -1 przy bledzie
if (deskryptor_serwera == -1) {
perror("Serwer: blad otwarcia FIFO");
printf("Serwer FIFO uruchomiony...\n");
// przechwycamy SIGINT (Ctrl+C)
signal(SIGINT, sigint_handler);
// nieskonczona petla, po to przechwycamy SIGTERM i SIGINT
// serwer blokuje sie na read, az klient nie przesle swojego PID,
// jesli przeslal niepelny PID (albo nieprawidlowy), to ignorujemy tego klienta i
// idziemy do nastepnej iteracji tj. czekania na PID od klienta
// warto zauwazyc ze oczekujemy na PID ktore klient przesle na FIFO-SERWER, bo
// bez tego nie utworzymy kolejek specjalnie dla tego numeru PID
if (read(deskryptor_serwera, &pid_klienta, sizeof(pid_t)) != sizeof(pid_t))
printf("Serwer: obsluga klienta %d\n", pid_klienta);
// nadpisujemy bufor nazwa kolejki do czytania (ma forme np. FIFO-1-5032)
sprintf(bufor, "/tmp/FIFO-1-%d", pid_klienta);
// tworzymy kolejke tylko do czytania
kolejka_czytania = open(bufor, O_RDONLY);
if (kolejka_czytania == -1) {
perror("Serwer: błąd otwarcia FIFO klienta (read)");
// nadpisujemy bufor nazwa kolejki do pisania (ma forme np. FIFO-2-5032)
sprintf(bufor, "/tmp/FIFO-2-%d", pid_klienta);
// tworzymy kolejke tylko do pisania
kolejka_pisania = open(bufor, O_WRONLY);
if (kolejka_pisania == -1) {
perror("Serwer: blad otwarcia FIFO klienta (write)");
// serwer blokuje sie na read, az klient nie przesle liczby,
// jesli przeslal cala liczbe to obliczamy wynik i przesylamy mu go
// (wypisujac do kolejki do pisania)
if (read(kolejka_czytania, &liczba, sizeof(int)) == sizeof(int)) {
write(kolejka_pisania, &wynik, sizeof(int));
printf("Serwer: %d -> %d\n", liczba, wynik);
Klient FIFO – wersja do serwera sekwencyjnego
2 (pisze) -----> 1 (czyta)
1 (czyta) <----- 2 (pisze)
1. nadpisujemy bufory nazwami kolejek
2. na wszelki zamykamy stare kolejki
3. tworzymy kolejki z mknod()
4. probujemy otworzyc kolejke serwera
7. wysylamy liczbe i czekamy na wynik
const char *nazwa_serwera = "/tmp/FIFO-SERWER";
char bufor1[256], bufor2[256]; // bufor na nazwy klienta
int kolejka_czytania, kolejka_pisania; // deskryptory
pid_t pid = getpid(); // PID naszego klienta
// zamykamy stare kolejki klientow (na wszelki)
// nadpisujemy bufor nazwa kolejki do pisania (ma forme np. FIFO-1-5032)
sprintf(bufor1, "/tmp/FIFO-1-%d", pid);
// nadpisujemy bufor nazwa kolejki do czytania (ma forme np. FIFO-1-5032)
sprintf(bufor2, "/tmp/FIFO-2-%d", pid);
// tworzenie kolejki FIFO z prawami dostepu tylko wlasciciela (0600),
// mknod zwaraca -1 przy bledzie
if (mknod(bufor1, S_IFIFO | 0600, 0) == -1) {
perror("Klient: blad tworzenia FIFO 1");
// tworzenie kolejki FIFO z prawami dostepu tylko wlasciciela (0600),
// mknod zwaraca -1 przy bledzie
if (mknod(bufor2, S_IFIFO | 0600, 0) == -1) {
perror("Klient: blad tworzenia FIFO 2");
// probujemy polaczyc sie z serwerem tylko do pisania
// (w serwerze jest taka sama linijka tylko z O_RDONLY)
deskryptor_serwera = open(nazwa_serwera, O_WRONLY);
if (deskryptor_serwera == -1) {
perror("Klient: nie moge połaczyc sie z serwerem");
// wyslamy PID do serwera, zeby mogl utworzyc kolejki dla naszego PIDu
write(deskryptor_serwera, &pid, sizeof(pid_t));
// zamykamy polaczenie z kolejka serwera (FIFO-SERWER)
// i przy okazji zamykami inne
close(deskryptor_serwera);
// otwieramy kolejke tylko do pisania
kolejka_pisania = open(bufor1, O_WRONLY);
if (kolejka_pisania == -1) {
perror("Klient: blad otwarcia FIFO do pisania");
// otwieramy kolejke tylko do czytania
kolejka_czytania = open(bufor2, O_RDONLY);
if (kolejka_czytania == -1) {
perror("Klient: blad otwarcia FIFO do czytania");
printf("Podaj liczbe: ");
write(kolejka_pisania, &liczba, sizeof(int));
// i czeka na wynik od serwera
read(kolejka_czytania, &wynik, sizeof(int));
printf("Wynik: %d * %d = %d\n", liczba, liczba, wynik);
//IPC przerobiony na wysylanie charow
#include <ctype.h> // Potrzebne do toupper()
char tekst[256]; // Zmieniono z int na tablicę char
char *sciezka = "/tmp/serwer.ipc";
int plik = open(sciezka, O_CREAT, 0600);
perror("Serwer: Blad utworzenia pliku");
key_t klucz_serwera = ftok(sciezka, 0);
int kolejka_serwera = msgget(klucz_serwera, IPC_CREAT | 0600);
if (kolejka_serwera == -1) {
perror("Serwer: msgget");
printf("Serwer tekstowy uruchomiony.\n");
// Odbiór zgłoszenia (mtype 1)
if (msgrcv(kolejka_serwera, &handshake, sizeof(paczka1) - sizeof(long), 1, 0) == -1) {
int kolejka_klienta = msgget(klucz_klienta, 0600);
// Odbiór tekstu od klienta (mtype 2)
msgrcv(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 2, 0);
printf("Serwer: otrzymano tekst: %s\n", pakiet.tekst);
// MODYFIKACJA: Zamiana na wielkie litery
for (int i = 0; pakiet.tekst[i] != '\0'; i++) {
pakiet.tekst[i] = (char)toupper(pakiet.tekst[i]);
pakiet.mtype = 3; // Odsyłamy jako wynik (mtype 3)
msgsnd(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 0);
printf("Serwer: zmodyfikowany tekst odeslany.\n");
char tekst[256]; // Zgodność z serwerem
char *sciezka = "/tmp/serwer.ipc";
key_t klucz_serwera = ftok(sciezka, 0);
int kolejka_serwera = msgget(klucz_serwera, 0600);
key_t klucz_klienta = ftok(sciezka, pid);
int kolejka_klienta = msgget(klucz_klienta, 0600 | IPC_CREAT);
/* Zgłoszenie do serwera (handshake) */
msgsnd(kolejka_serwera, &handshake, sizeof(paczka1) - sizeof(long), 0);
/* Pobieranie tekstu od użytkownika */
printf("Klient: Wpisz wiadomosc do serwera: ");
// Używamy fgets dla bezpiecznego pobrania tekstu
fgets(pakiet.tekst, sizeof(pakiet.tekst), stdin);
// Usunięcie znaku nowej linii '\n' dodanego przez fgets
pakiet.tekst[strcspn(pakiet.tekst, "\n")] = 0;
pakiet.mtype = 2; // mtype dla danych wysyłanych
msgsnd(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 0);
/* Odbiór wyniku od serwera (mtype 3) */
msgrcv(kolejka_klienta, &pakiet, sizeof(paczka2) - sizeof(long), 3, 0);
printf("Klient: Wynik z serwera: %s\n", pakiet.tekst);
// Sprzątanie kolejki klienta po zakończeniu
msgctl(kolejka_klienta, IPC_RMID, NULL);