HTML

Programozó Páternoszter

Ez a Programozó Páternoszter (PP) blogja, a programozásról szól. Aktualitása, hogy a Debreceni Egyetem Informatikai Kara Magasszintű programozási nyelvek 1-2, C++ esattanulmányok, Java esettanulmányok című kurzusainak blogja is egyben.

A vadászat

A Debreceni Egyetem Programozói Évkönyve: az UDPROG projekt. A szakmai fórumunk a Facebook-en. Az új előadások a prezin.
A régi előadások:
Prog1:
1. C bevezetés
2. C tárgyalás
3. C befejezés
4. C a gyakorlatban
5. C++ bevezetés
6. C++ tárgyalás
7. C++ befejezés
8. C++ a gyakorlatban
9. Java platform bevezetés
10. Kvantuminformatikai alg. bev.
Prog2:
1. Java bevezetés
2. Java tárgyalás
3. Java befejezés
4. Java a gyakorlatban
5. Software Engineering bev.
6. Java EE bevezetés
7. AspectJ bevezetés
8. BPMN-BPEL SOA programozás
9. C++ haladó
10. Tensorflow

Kövess engem!

Friss topikok

Linkblog

Hálózati vegyérték

2011.03.06. 19:00 nb

Ha a képzési hálóban a tárgyak kovalens kötéssel kapcsolódnának, akkor a ráépülő Hálózatok tárgy felé az alábbi példa feldolgozásával kötünk majd. Ez egy egyszerű hálózati TCP/IP szerverprogi, amit próbáltunk állatorvosi módon elkészíteni, mert lesz benne:

  • fork
  • socket programozás (UNIX-ban minden fájl)
  • multiplexelés (a select rendszerhívás)
  • jelkezelés
  • szemaforok
  • osztott memória használata

 A program első iniciális változatának összedobása után lássuk a tesztelést:

Eddig ez kíméletes volt, de laborkísérletezzünk vele: a kliens nyomja párhuzamosabban, vegyük ki/be a szemaforos védelmet a szerveren és tegyünk be egy kis alvós késleltetést a kiszolgálásba! Miket tapasztalunk? Egy trófea annak, aki demonstrálja, hogy elromlik az örök válasz: a 42.

Lapozz tovább a forrásokért:

szerver.c

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <sys/wait.h>

#define SZERVER_PORT 2006
#define SZERVER_SOR_MERET 10
#define CTIME_BUFFER_MERET 128

int
kiszolgal (int kliens, int szemafor, int *osztott_memoria_terulet)
{

    char buffer[CTIME_BUFFER_MERET] = "";
    time_t t = time (NULL);
    char *ts = ctime_r (&t, buffer);
    char buffer2[256] = "";

    struct sembuf zar, nyit;
    zar.sem_num = 0;
    zar.sem_op = -1;
    nyit.sem_num = 0;
    nyit.sem_op = 1;

    int olvasott = read (kliens, buffer2, 10);
    write (kliens, buffer2, olvasott);

    if (semop (szemafor, &zar, 1) == -1)
    {
        perror ("semop");
        exit (EXIT_FAILURE);
    }

    ++*(osztott_memoria_terulet+1);

    if (buffer2[0] == '+')
        ++*osztott_memoria_terulet;
    else
        --*osztott_memoria_terulet;

    olvasott = snprintf(buffer2, 50, "Ertek=%d Kliensek=%d\n", *osztott_memoria_terulet, *(osztott_memoria_terulet+1));

    // debug
    // printf ("%d\n", *osztott_memoria_terulet);
    // fflush (stdout);

    if (semop (szemafor, &nyit, 1) == -1)
    {
        perror ("semop");
        exit (EXIT_FAILURE);
    }

    write (kliens, buffer2, olvasott);

    return write (kliens, ts, strlen (ts));
}

void
zombi_elharito (int sig)
{
    while (wait (NULL) > 0)
        ;
}

int
main (void)
{
    int kapu_figyelo, kapcsolat, kliensm,
    sockoptval = 1, s, gyermekem_pid, szemafor;
    fd_set kapu_figyelok;
    int osztott_memoria;
    int *osztott_memoria_terulet;
    struct timeval timeout;
    struct sockaddr_in szerver, kliens;
    struct sigaction sa;
    sa.sa_handler = zombi_elharito;
    sigemptyset (&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    memset ((void *) &szerver, 0, sizeof (szerver));
    szerver.sin_family = AF_INET;
    inet_aton ("127.0.0.1", &(szerver.sin_addr));
    szerver.sin_port = htons (SZERVER_PORT);
    if ((kapu_figyelo = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
        perror ("socket");
        exit (EXIT_FAILURE);
    }
    setsockopt (kapu_figyelo, SOL_SOCKET, SO_REUSEADDR,
                (void *) &sockoptval, sizeof (sockoptval));
    fcntl (kapu_figyelo, F_SETFL, fcntl (kapu_figyelo, F_GETFL) | O_NONBLOCK);
    if (bind (kapu_figyelo, (struct sockaddr *) &szerver,
              sizeof (szerver)) == -1)
    {
        perror ("bind");
        exit (EXIT_FAILURE);
    }
    if (listen (kapu_figyelo, SZERVER_SOR_MERET) == -1)
    {
        perror ("listen");
        exit (EXIT_FAILURE);
    }
    printf ("%s:%d\n", inet_ntoa (szerver.sin_addr), ntohs (szerver.sin_port));

    if ((szemafor =
                semget (ftok (".", 42), 1, IPC_CREAT | S_IRUSR | S_IWUSR)) == -1)
    {
        perror ("semget");
        exit (EXIT_FAILURE);
    }
    printf ("szemafor: %d\n", szemafor);
    fflush (stdout);
    if (semctl (szemafor, 0, SETVAL, 1))
    {
        perror ("semctl");
        exit (EXIT_FAILURE);
    }
    if ((osztott_memoria =
                shmget (ftok (".", 44), 2*sizeof(int), IPC_CREAT | S_IRUSR | S_IWUSR)) == -1)
    {
        perror ("shmget");
        exit (EXIT_FAILURE);
    }
    if ((osztott_memoria_terulet = (int *)shmat (osztott_memoria, NULL, 0)) < 0)
    {
        perror ("shmat");
        exit (EXIT_FAILURE);
    }
    *osztott_memoria_terulet = 42;
    *(osztott_memoria_terulet+1) = 0;
    sigaction (SIGCHLD, &sa, NULL);
    FD_ZERO (&kapu_figyelok);
    for (;;)
    {
        FD_SET (kapu_figyelo, &kapu_figyelok);
        timeout.tv_sec = 3;
        timeout.tv_usec = 0;
        if ((s = select (kapu_figyelo + 1, &kapu_figyelok, NULL,
                         NULL, &timeout)) == -1)
        {
            switch (errno)
            {
            case EBADF:
                printf ("EBADF\n");
                break;
            case EINTR:
                printf ("EINTR\n");
                break;
            case EINVAL:
                printf ("EINVAL\n");
                break;
            case ENOMEM:
                printf ("ENOMEM\n");
                break;
            }
            fflush (stdout);
//exit (EXIT_FAILURE);
        }
        else if (!s)
        {
            printf ("vartam...\n");
            fflush (stdout);
        }
        else
        {
            if (FD_ISSET (kapu_figyelo, &kapu_figyelok))
            {
                memset ((void *) &kliens, 0, (kliensm = sizeof (kliens)));
                if ((kapcsolat = accept (kapu_figyelo,
                                         (struct sockaddr *) &kliens,
                                         (socklen_t *) & kliensm)) == -1)
                {
                    perror ("accept");
                    exit (EXIT_FAILURE);
                }
                printf (" <-> %s:%d\n",
                        inet_ntoa (kliens.sin_addr), ntohs (kliens.sin_port));
                if ((gyermekem_pid = fork ()) == 0)
                {
                    close (kapu_figyelo);
                    if (kiszolgal (kapcsolat, szemafor, osztott_memoria_terulet) == -1)
                    {
                        perror ("kiszolgal");
                    }
                    close (kapcsolat);
                    exit (EXIT_SUCCESS);
                }
                else if (gyermekem_pid > 0)
                {
// wait(&statusz); e miatt kezeljuk a SIGCHLD jelet,
// l. a Zombik fejezetet!
                    close (kapcsolat);
                }
                else
                {
                    close (kapcsolat);
                    perror ("fork");
                    exit (EXIT_FAILURE);
                }
            }
        }
    }
}

 

kliens.c 

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SZERVER_PORT 2006
#define BUFFER_MERET 256

int
kliens (char b)
{
    int kapu, olvasva;
    struct sockaddr_in szerver;
    char buffer[BUFFER_MERET];
    memset ((void *) &szerver, 0, sizeof (szerver));
    szerver.sin_family = AF_INET;
    inet_aton ("127.0.0.1", &(szerver.sin_addr));
    szerver.sin_port = htons (SZERVER_PORT);
    if ((kapu = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
    {
        perror ("socket");
        return -1;
    }
    if (connect (kapu, (struct sockaddr *) &szerver, sizeof (szerver)) == -1)
    {
        perror ("connect");
        return -1;
    }
    write(kapu, &b, 1);
    write(kapu, &b, 1);
    while ((olvasva = read (kapu, buffer, BUFFER_MERET)) > 0)
        write (1, buffer, olvasva);
    return 0;
}

int
main (int argc, char *argv[])
{
    for (int i=0; i<1000; ++i)
        kliens(argv[1][0]);

    exit (EXIT_SUCCESS);
}

 

(Ha valami nem világos, még nem probléma, az érintett témákat az 5. előadáson tárgyaljuk.)

Szólj hozzá!

Címkék: select fork socket szemafor osztott memória multiplexelés

A bejegyzés trackback címe:

https://progpater.blog.hu/api/trackback/id/tr82712622

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása