Erinevus lehekülje "C" redaktsioonide vahel

Allikas: Kuutõrvaja
 
(ei näidata sama kasutaja 3 vahepealset redaktsiooni)
11. rida: 11. rida:
 
Kahjuks paljud OS-id ei võimaldagi neid probleeme käisitleda, vähemalt praktiliselt on see neis keeruline.
 
Kahjuks paljud OS-id ei võimaldagi neid probleeme käisitleda, vähemalt praktiliselt on see neis keeruline.
 
   
 
   
 
 
Fakt on see, et kes on ennast kasvõi linux'isse sisse loginud on kasutanud exec'it ja kes on käsurealt teinud ls on kasutanud neid mõlemat. Niisiis, praktilised asjad. Vaatame näite varal kuidas süsteem töötab.
 
Fakt on see, et kes on ennast kasvõi linux'isse sisse loginud on kasutanud exec'it ja kes on käsurealt teinud ls on kasutanud neid mõlemat. Niisiis, praktilised asjad. Vaatame näite varal kuidas süsteem töötab.
  
19. rida: 18. rida:
 
Igal protsessil on olemas identifikaator (PID) ja parent identificator (PPID). Idee on selles, et kui on olemas protsess, siis peab olema või olnud olema mingi teine protsess mis on ta nö. sünnitanud. Kõneldakse emast ja tütardest. Kui tütar ära tappa jääb ema ellu ja vastupidi (kill PID).
 
Igal protsessil on olemas identifikaator (PID) ja parent identificator (PPID). Idee on selles, et kui on olemas protsess, siis peab olema või olnud olema mingi teine protsess mis on ta nö. sünnitanud. Kõneldakse emast ja tütardest. Kui tütar ära tappa jääb ema ellu ja vastupidi (kill PID).
 
   
 
   
 
 
===Protsessi PID, PPID ja ps -l===
 
===Protsessi PID, PPID ja ps -l===
  
39. rida: 37. rida:
 
  bash# loputa_while &
 
  bash# loputa_while &
  
, nii läheb ta kohe backgroundi
+
nii läheb ta kohe backgroundi
  
 
Käsu ps -l abil peaks PID ja PPID näha olema
 
Käsu ps -l abil peaks PID ja PPID näha olema
45. rida: 43. rida:
 
  bash# ps l
 
  bash# ps l
 
   FLAGS  UID  PID  PPID PRI  NI  SIZE  RSS WCHAN      STA TTY TIME COMMAND
 
   FLAGS  UID  PID  PPID PRI  NI  SIZE  RSS WCHAN      STA TTY TIME COMMAND
    100    0    89    1  0  0  1176  632 setitimer  S    1  0:00 -bash
 
    100    0    91    1  0  0    840  296 UMSDOS_link S    3  0:00 /sbin/agetty 38400 tty3 li
 
    100    0    92    1  0  0    840  296 UMSDOS_link S    4  0:00 /sbin/agetty 38400 tty4 li
 
    100    0    93    1  0  0    840  296 UMSDOS_link S    5  0:00 /sbin/agetty 38400 tty5 li
 
    100    0    94    1  0  0    840  288 UMSDOS_link S    6  0:00 /sbin/agetty 38400 tty6 li
 
100100    0  141    1  0  0  2456  1480 posix_lock_ S    1  0:00 xterm -geometry 80x30+90+0
 
    100    0  144    1  0  0  20520 16444 posix_lock_ S    1  2:13 /usr/local/netscape/netsca
 
100100    0  676    1  0  0  2524  1444 posix_lock_ S    1  0:00 /usr/bin/X11/xterm -sb -sl
 
100000    0  128    89  0  0  1132  492 setitimer  S    1  0:00 sh /usr/X11/bin/startx
 
    100    0  129  128  0  0  1888  620 setitimer  S    1  0:00 xinit /usr/X11R6/lib/X11/x
 
    100    0  131  129  0  0  1128  476 setitimer  S    1  0:00 sh /usr/X11R6/lib/X11/xini
 
    100    0  136  131  0  0  1684  796 posix_lock_ S    1  0:04 fvwm
 
100100    0  138  136  0  0  1496  604 posix_lock_ S    1  0:00 /usr/lib/X11/fvwm/FvwmPage
 
    100    0  142  141  10  0  1184  648 setitimer  S  p0  0:00 bash
 
 
  100000    0  888  142  12  0    828  184            R  p0  0:23 loputa_while
 
  100000    0  888  142  12  0    828  184            R  p0  0:23 loputa_while
 
  100000    0  889  142  13  0    828  184            R  p0  0:17 loputa_while
 
  100000    0  889  142  13  0    828  184            R  p0  0:17 loputa_while
100100    0  892  142  12  0    988  376            R  p0  0:00 ps l
 
100100    0  145  144  0  0  12496  2496 posix_lock_ S    1  0:00 (dns helper)
 
    100    0  677  676  0  0  1188  640 setitimer  S  p1  0:00 -bash
 
    100    0  835  677  0  0  1228  600 UMSDOS_link S  p1  0:00 joe f2.c
 
 
  bash#  
 
  bash#  
  
122. rida: 102. rida:
 
   FLAGS  UID  PID  PPID PRI  NI  SIZE  RSS WCHAN      STA TTY TIME COMMAND
 
   FLAGS  UID  PID  PPID PRI  NI  SIZE  RSS WCHAN      STA TTY TIME COMMAND
 
  100100    0  949  142  8  0    832  232 setitimer  S  p0  0:00 tegeleb_magajaga
 
  100100    0  949  142  8  0    832  232 setitimer  S  p0  0:00 tegeleb_magajaga
100100    0  145  144  3  0  12496  2496 posix_lock_ S    1  0:00 (dns helper)
 
    100    0  677  676  11  0  1188  640 setitimer  S  p1  0:00 -bash
 
100100    0  951  677  13  0    988  376            R  p1  0:00 ps l
 
 
  100100    0  950  949  9  0    832  232 dump_fpu    S  p0  0:00 ma_magan
 
  100100    0  950  949  9  0    832  232 dump_fpu    S  p0  0:00 ma_magan
  
130. rida: 107. rida:
 
   
 
   
 
   
 
   
 
 
===Ühe programi seest teise käivitamine - fork()===
 
===Ühe programi seest teise käivitamine - fork()===
  
165. rida: 141. rida:
 
  bash# ps l
 
  bash# ps l
 
   FLAGS  UID  PID  PPID PRI  NI  SIZE  RSS WCHAN      STA TTY TIME COMMAND
 
   FLAGS  UID  PID  PPID PRI  NI  SIZE  RSS WCHAN      STA TTY TIME COMMAND
    100    0  142  141  8  0  1184  652 setitimer  S  p0  0:00 bash
 
 
  100000    0  999  142  9  0    828  184 setitimer  S  p0  0:00 f1
 
  100000    0  999  142  9  0    828  184 setitimer  S  p0  0:00 f1
100100    0  145  144  0  0  12496  2496 posix_lock_ S    1  0:00 (dns helper)
 
    100    0  677  676  13  0  1188  640 setitimer  S  p1  0:00 -bash
 
100100    0  1001  677  15  0    988  376            R  p1  0:00 ps -l
 
 
     140    0  1000  999  9  0    832  232 dump_fpu    S  p0  0:00 f1
 
     140    0  1000  999  9  0    832  232 dump_fpu    S  p0  0:00 f1
  
628. rida: 600. rida:
 
Kasutamine: käivitage ühes X-i aknas server ja teises klient ning veenduge, et suhtlemine toimub. Modifitseerige ja püüdke aru saada :)
 
Kasutamine: käivitage ühes X-i aknas server ja teises klient ning veenduge, et suhtlemine toimub. Modifitseerige ja püüdke aru saada :)
  
Seda ma ei tahks komenteerida kuna ma ei oska :(
+
Seda ma tahaks komenteerida kuid ei oska :(
  
 
aga vaadake orginaalallikat sisukorrast!
 
aga vaadake orginaalallikat sisukorrast!

Viimane redaktsioon: 2. oktoober 2009, kell 15:16

Sissejuhatus.

Ilmselt on programeerimine erinevates programmeerimiskeeltes nagu tavaliste keelte rääkimine. Võib vabalt ära õppida nt. prantsuse keele (st. sõnad ja põhilised grammatikareeglid) kuid ikkagi rääkida prantsuse keelt nagu eesti keelt; või nagu inglise või vene keelt. Sarnane on asi ka programmeerimises. Võib küll tunda C keele süntaksit, aga kui enne on omandatud kõva harjumus Basic'us või Pascal'is programmeeida võib mitte märgata C keelele iseloomulikke võimalusi ning tulemusena on C keele programmid kirjutatud sisuliselt Pascalis kuigi kasutati C süntaksit :) Üks asi, mis on C-le iseloomulik on nt. pointeritega vaba ümberkäimine.

Järgnevas vaatame võimalusi, mida saab kasutada programmeerides C keeles talle kõige loomulikumas keskkonnas: UNIX'is sh Linux'is. Samas peaks siin selginema arusaam protssidest selles mõttes, et

  • kes kelle sünnitab
  • kuidas protsessid saavad omavahel infot vahetada

Kahjuks paljud OS-id ei võimaldagi neid probleeme käisitleda, vähemalt praktiliselt on see neis keeruline.

Fakt on see, et kes on ennast kasvõi linux'isse sisse loginud on kasutanud exec'it ja kes on käsurealt teinud ls on kasutanud neid mõlemat. Niisiis, praktilised asjad. Vaatame näite varal kuidas süsteem töötab.

  • programm - fail infokandljal, mida saaks käivitada
  • protsess - käivitatud faili koopia mälus kusjuures ühte programmi saab mitu korda käivitada. St ühele programmile võib vastata mitu sarnast koopiat mälus.

Igal protsessil on olemas identifikaator (PID) ja parent identificator (PPID). Idee on selles, et kui on olemas protsess, siis peab olema või olnud olema mingi teine protsess mis on ta nö. sünnitanud. Kõneldakse emast ja tütardest. Kui tütar ära tappa jääb ema ellu ja vastupidi (kill PID).

Protsessi PID, PPID ja ps -l

Vaatame kuidas on seotud ja paistavad sissejuhatuse lõpus öeldud väited praktikas.

Eesmärk: loome programmi loputa_while.c ja käivitame ta. Vaatame mis on ta PID ja PPID.

loputa_while.c:

#include<stdio.h>
main()
{
while(1);
return 0;
}

Käivitada on hea

bash# loputa_while &

nii läheb ta kohe backgroundi

Käsu ps -l abil peaks PID ja PPID näha olema

bash# ps l
 FLAGS   UID   PID  PPID PRI  NI   SIZE   RSS WCHAN       STA TTY TIME COMMAND
100000     0   888   142  12   0    828   184             R   p0  0:23 loputa_while
100000     0   889   142  13   0    828   184             R   p0  0:17 loputa_while
bash# 

Antud juhul on käivitatud programm kahel korral (PID 888, 889); xterm'i aken on 141 milles on bash 142. Pange tähele, et PPID on mõlemal loputa_while'l sama.

Ja tappa saab nad:

bash# kill 888
bash# kill 889

või

bash# killall loputa_while

Ühe programi seest teise käivitamine - system()

Näide 2:

Kutsume programmi seest teise programmi välja:

Illusreerime juhtumit kahe programmi koos kasutamisega

ma_magan.c

#include<stdio.h>
main()
{
printf("hrr.. hrrr....\n");
sleep(5);
return 0;
}

tegeleb_magajaga.c

#include<stdio.h>
main()
{
printf("Siin on magajaga tegeleja algus ..\n");
system("ma_magan");
printf("Ja siin on magajaga tegeleja lõpp\n");
return 0;
}

Kui need samas kataloogin ära kompilleerida ja viimane tööl panna peaks juhtuma järgmine:

bash# tegeleb_magajaga
Siin on magajaga tegeleja algus ..
hrr.. hrrr....
(paus 5 sekundit)
Ja siin on magajaga tegeleja lõpp
bash#

Loo moraal on selles, et seni kuni system() 'i täidetakse peab allpool olev programmi osa ootama. Vaadake mida teevad PID ja PPID'd (seda peab tegema teises aknas kui programmid veel töötavad):

bash# ps l
 FLAGS   UID   PID  PPID PRI  NI   SIZE   RSS WCHAN       STA TTY TIME COMMAND
100100     0   949   142   8   0    832   232 setitimer   S   p0  0:00 tegeleb_magajaga
100100     0   950   949   9   0    832   232 dump_fpu    S   p0  0:00 ma_magan

Näeb, et tegeleb _magajaga on emaks ma_magan 'ile.


Ühe programi seest teise käivitamine - fork()

vaatame aga ka teist võimalust (huvitavamat ?) teist programmi esimesest välja kutsuda:

#include<stdio.h>
main()
{
    int pid, status;
    pid = fork();
    if (pid == -1)
        {
            printf("jama\n"); exit(1);
        }

    if (pid == 0)
        { /* Juurde tekkinud protsess mille PID'i teab ema */
            sleep(1);
            printf("Mina olen tütar\n");
            sleep(4);
        }

    else
        {
            wait(&status);  /* Ema ootab kuni tütar oma tegevuse lõpetab */
            printf("Mina olen emme, tütre status: %d tütre PID: %d\n", status, pid);
        }

    return 0;
}

Kui siin programmi täitmise ajal vaadata PID ja PPID'e näeb:

bash# ps l
 FLAGS   UID   PID  PPID PRI  NI   SIZE   RSS WCHAN       STA TTY TIME COMMAND
100000     0   999   142   9   0    828   184 setitimer   S   p0  0:00 f1
   140     0  1000   999   9   0    832   232 dump_fpu    S   p0  0:00 f1

Pange tähele, et on tekkinud kaks f1'te: ema ja tütar.

Tütre nö. sünnitab käsk

pid = fork()

kus juures pid on muutuja mis omab ühe programmis sees juskui kahte väärtust ?? Fakt on see, et toodud konstruktsioon tekitab juurde teise (nö. tütre) protsessi.

Mis aga on oluline, ema ei pruugi tütrse tegevuse lõppu ära ootama!

kommenteerige rida wait .. välja:

   /* wait(&status);  Ema ootab kuni tütar oma tegevuse lõpetab */

Tulemusena jätkab ema kohe edasi ja tütar samal ajal kah. Siin võib kiirust reguleerida nt. sleep'iga.

Kui see asi teil toimib, siis olete võimelised küll väga primitiivsel kombel,aga siiski looma protsesse C keeles programmeerides. wait'i mitte väljakommenteerimine on analoogiline käsurealt nt. 'updatedb' andmisega; kui ta ga väljakommenteerida siis on see sama hea kui 'updatedb &' - saab prompti kohe tagasi.


Ühe programmi teisega asendamine execl()

Ja veel, on kõelemata execl'i roll. Nimelt, linux suudab asendada ühe protsessi teisega, kusjuures teine omandab esimese PID'i ja veel palju muid esimese omadusi.

Eesmärk: loome neli programmi mis kutsuvad üksteist ringiratast välja, ad infinitum

emme.c

#include<stdio.h>
main()
{
printf("Mina olen emme, muutun tütreks, onuks, pojaks ja tagasi emmeks ..\n");
sleep(3);
execl("/root/net/tytar", "tytar", 0);
return 0;
}

tytar.c

#include<stdio.h>
main()
{
printf("Mina olen tütar ..\n");
sleep(3);
execl("/root/net/onu", "onu", 0);
return 0;
}

onu.c

#include<stdio.h>
main()
{
printf("Mina olen onu ..\n");
sleep(3);
execl("/root/net/poeg", "poeg", 0);
return 0;
}

poeg.c

#include<stdio.h>
main()
{
printf("Mina olen poeg ..\n");
sleep(3);
execl("/root/net/emme", "emme", 0);
return 0;
}

Kui nüüd emme (tegelikult ükskõik milline neist) käivitada, siis algab ring pihta ja jälgides ps -ga võib veenduda,et sama PID number identifitseerib vaheldumisi erinevad programme. Paraku pole ma suutnud mõelda välja sellisele asjale praktilist rakendust aga kas arvutitel üldse on praktilist rakendust? Küllap on.

Midagi sarnast toimub arvutisse sisselogimisel:

- ekraanil on ees login prompt mile viis sinna getty - peale ime sisestust asenub getty programmmiga login mis tegeleb teie kasutajatunnusega - lõpuks asendub login bash'iga või mis iganes teie shelliks on pandud (nt. pine, passwd).


fifo - named pipe

Pobleemiks on saada kaks samal ajal töötavat programmi panna omavahel infot vahetama. Paraku küll ühes suunas, st. üks annab, teine saab.

Muide võtet 'who | wc -l' 'i nimetatakse unnamed pipe'ks. See langeb samuti kategooriasse kahe programmi vaheline info vahetamine. Tegelikult saab fifo-ga kombineerida ka enam kui kaks programmi suhtlema panna.

Teeme ühe näite:

fifo_server.c:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define FIFO "fifo.1"
#define MAXBUFF 80
main()
{
int readfd, n;
char buff[MAXBUFF];
if (mknod(FIFO, S_IFIFO | 0666, 0) < 0) {
        printf("Ei saa FIFOt luua\n"); exit(1);}

if ((readfd=open(FIFO, O_RDONLY)) < 0) {
        printf("Ei saa avada FIFOt\n"); exit(1);}

while ((n=read(readfd, buff, MAXBUFF)) > 0)
        {
        if (write(1, buff, n) !=n)
        {
                printf("Sisestamisel viga\n"); exit(1);
       }
        }
       close (readfd);
       exit(0);
}

fifo_client.c:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define FIFO "fifo.1"
main()
{
int writefd, n;
if ((writefd=open(FIFO, O_WRONLY)) < 0){
        printf("Ei saa avada FIFOt\n"); exit(1);}

if (write(writefd, "Tere Maailm!\n", 13) != 13){
       printf ("Kirjutamisel viga\n"); exit(1);}

close(writefd);
if (unlink(FIFO) < 0){
        printf("Ei saa unlinkida FIFOt\n"); exit(1);}

exit(0);
}

Kasutamiseks tuleb nad mõlemad ära kompilleerida ja ühes X-i aknas käivitada serv ja seejärel teises klient. Tulemusena peaks serveri aknasse ilmuma tekst 'Tere Maailm!'


Message

Järgnev tehnika võimaldab samuti protsesside vahel infot vahetada. Kopileerige ära, käivitage enne ühes aknas server ja teises klient ning veenduge, et midagi toimub!

mesg.h:

#define MAXBUFF 80
#define PERM 0666
typedef struct our_msgbuf {
        long mtype;
        char buff[MAXBUFF];
        } Message;

mess_server.c:

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include "mesg.h"

main()
{
    Message message;
    key_t   key;
    int msgid, length, n;

    if ((key=ftok("server", 'A')) < 0)
        {
            printf("jama 1\n"); exit(1);
        }

    message.mtype=1;

    if ((msgid=msgget(key, PERM | IPC_CREAT)) < 0)
        {
            printf("jama 2\n"); exit (1);
        }

    while (1)
        {
            n=msgrcv(msgid, (void *) &message, sizeof(message), message.mtype, 0);
            if (n > 0)
                {
                    if (write(1, message.buff, n) !=n )
                        {
                            printf("jama 3\n"); exit (1);
                       }
               }
           else
               {
                   printf("jama 4\n"); exit (1);
               }
       }
   exit(0);
}

mess_client.c:

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include "mesg.h"

main()
{
    Message message;
    key_t   key;
    int msgid, length, i=0;
    char mess[40];

    message.mtype=1;

    if ((key=ftok("server", 'A')) < 0)
        {
            printf("jama 1\n"); exit(1);
        }

   if ((msgid=msgget(key, 0)) < 0)
       {
           printf("jama 2\n"); exit (1);
       }

   while (i < 7)
       {
           i=i++;
           sleep(1);
           sprintf(mess, "%d. No on ..\n", i);
           if ((length=sprintf(message.buff, mess)) < 0)
               {
                   printf("jama jalle\n"); exit (1);
               }

           if (msgsnd(msgid, (void *) &message, length, 0) !=0)
               {
                   printf("jalle jamm\n"); exit(1);
               }
       }
   if (msgctl(msgid, IPC_RMID, 0) < 0)
       {
           printf("jah, jalle\n"); exit(1);
       }

    exit(0);
}

Socets - AF_INET

Ka see on tehnika, mis võimaldab protsesside vahel infot vahetada: need protsessid aga ei pruugi toimuda ühes samas masinas. Praktilistest rakendustest võiks mainida

- ftpd ja ftp
- httpd ja lynx
- inetd ja telnet

Tundes tehnikat saab selles liinis palju korda saata. Mõned autorid toovad paralleeli telefoniga helistamisest. Järgnevat võiks saata selline ettekujutus: On kaks arvutit, IP numbritega ja töötava võrgutarkvaraga (st. n - seeria); neil kummalgi on selliseid infot sisse-väljalaskvaid mulke nö. porte ehk soketeid 2^16 tükki. Esimesed 1024 on reserveeritud ja nende kasutust näeb failist /etc/services:

ftp             21/tcp
# 22 - unassigned
telnet          23/tcp
# 24 - private
smtp            25/tcp          mail
# 26 - unassigned
time            37/tcp          timserver
time            37/udp          timserver
rlp             39/udp          resource        # resource location
nameserver      42/tcp          name            # IEN 116
whois           43/tcp          nicname
domain          53/tcp          nameserver      # name-domain server
domain          53/udp          nameserver
mtp             57/tcp                          # deprecated
bootps          67/tcp          # BOOTP server
bootps          67/udp
bootpc          68/tcp          # BOOTP client
bootpc          68/udp
tftp            69/udp
gopher          70/tcp          # Internet Gopher
gopher          70/udp
rje             77/tcp          netrjs
finger          79/tcp
www             80/tcp          http    # WorldWideWeb HTTP
www             80/udp                  # HyperText Transfer Protocol
link            87/tcp          ttylink
kerberos        88/tcp          krb5    # Kerberos v5
kerberos        88/udp
supdup          95/tcp
# 100 - reserved
hostnames       101/tcp         hostname        # usually from sri-nic
iso-tsap        102/tcp         tsap            # part of ISODE.
csnet-ns        105/tcp         cso-ns  # also used by CSO name server
csnet-ns        105/udp         cso-ns
rtelnet         107/tcp         # Remote Telnet
rtelnet         107/udp
pop2            109/tcp         postoffice      # POP version 2
pop2            109/udp
pop3            110/tcp         # POP version 3
pop3            110/udp

Eesmärk:

- panna ühte arvutisse kuulama server mõne pordi taha ja
- teisest arvutist lasta mingi pordi kaudu tolle esimese masina serveri porti klient peale.

Kui server on valmis ja töötab, siis saab teda kontrollida kasutades kliendina nt. netscape'i, lynx'i või telnet'i.

Niisiis,

socket_server.c:

/*
** server.c -- a stream socket server demo
*/

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

#define MYPORT 3491    /* the port users will be connecting to */

#define BACKLOG 10     /* how many pending connections queue will hold */

main()
{
    int sockfd, new_fd, i;  /* listen on sock_fd, new connection on new_fd */
    struct sockaddr_in my_addr;    /* my address information */
    struct sockaddr_in their_addr; /* connector's address information */
    int sin_size;
    char teele[30];
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
         perror("socket");
         exit(1);
    }

    my_addr.sin_family = AF_INET;         /* host byte order */
    my_addr.sin_port = htons(MYPORT);     /* short, network byte order */
    my_addr.sin_addr.s_addr = INADDR_ANY; /* automatically fill with my IP */
    bzero(&(my_addr.sin_zero), 8);        /* zero the rest of the struct */

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
   }

    while(1) {  /* main accept() loop */
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
            perror("accept");
            continue;
        }
        printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
        if (!fork())

        { /* this is the child process */

        for (i=0; i < 10; i++)
        {
                sprintf(teele, "Hallo World %d
\n", i); if (send(new_fd, teele, 18, 0) == -1) perror("send"); } close(new_fd); exit(0); } close(new_fd); /* parent doesn't need this */ while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up all child processes */ } }

serverit saab kontrollida nt. nii:

bash# telnet  3491
bash# lynx localhost:3491
Netscape location: locahost:3491

Või sellise klient programmiga:

socket_client.c:

/*
** client.c -- a stream socket client demo
*/

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

#define PORT 3491    /* the port client will be connecting to */

#define MAXDATASIZE 100 /* max number of bytes we can get at once */

int main(int argc, char *argv[])
{
    int sockfd, numbytes;
    char buf[MAXDATASIZE];
    struct hostent *he;
    struct sockaddr_in their_addr; /* connector's address information */

    if (argc != 2) { 
        fprintf(stderr,"usage: client hostname\n");
        exit(1);
    }

    if ((he=gethostbyname(argv[1])) == NULL) {  /* get the host info */
        perror("gethostbyname");
        exit(1);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

  their_addr.sin_family = AF_INET;         /* host byte order */
    their_addr.sin_port = htons(PORT);     /* short, network byte order */
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);        /* zero the rest of the struct */

    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
        perror("connect");
        exit(1);
   }

   if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {
       perror("recv");
       exit(1);
   }

   buf[numbytes] = '\0';

   printf("Received: %s",buf);

   close(sockfd);

   return 0;
}

Kasutamine: käivitage ühes X-i aknas server ja teises klient ning veenduge, et suhtlemine toimub. Modifitseerige ja püüdke aru saada :)

Seda ma tahaks komenteerida kuid ei oska :(

aga vaadake orginaalallikat sisukorrast!