Ocenite etot tekst:

---------------------------------------------------------------
 http://wist.ifmo.ru/info/index.html
---------------------------------------------------------------
Dlya obespecheniya setevyh kommunikacij ispol'zuyutsya sokety. Soket eto konechnaya tochka setevyh kommunikacij. Kazhdyj ispol'zuyushchijsya soket imeet tip i associirovannyj s nim process. Sokety sushchestvuyut vnutri kommunikacionnyh domenov. Domeny eto abstrakcii, kotorye podrazumevayut konkretnuyu strukturu adresacii i mnozhestvo protokolov, kotoroe opredelyaet razlichnye tipy soketov vnutri domena. Primerami kommunikacionnyh domenov mogut byt': UNIX domen, Internet domen, i t.d.

V Internet domene soket - eto kombinaciya IP adresa i nomera porta, kotoraya odnoznachno opredelyaet otdel'nyj setevoj process vo vsej global'noj seti Internet. Dva soketa, odin dlya hosta-poluchatelya, drugoj dlya hosta-otpravitelya, opredelyayut soedinenie dlya protokolov, orientirovannyh na ustanovlenie svyazi, takih, kak TCP.


Sozdanie soketa

Dlya sozdaniya soketa ispol'zuetsya sistemnyj vyzov socket.

s = socket(domain, type, protocol);

|tot vyzov osnovyvaetsya na informacii o kommunikacionnom domene i tipe soketa. Dlya ispol'zovaniya osobennostej Internet, znacheniya parametrov dolzhny byt' sleduyushchimi:

communication domain -
AF_INET (Internet protokoly).
type of the socket -
SOCK_STREAM; |tot tip obespechivaet posledovatel'nyj, nadezhnyj, orientirovannyj na ustanovlenie dvustoronnej svyazi potok bajtov.
Vyshe byl upomyanut soket s tipom stream. Kratkoe opisanie drugih tipov soketov privedeno nizhe:
Datagram socket -
podderzhivaet dvustoronnij potok dannyh. Ne garantiruetsya, chto etot potok budet posledovatel'nym, nadezhnym, i chto dannye ne budut dublirovat'sya. Vazhnoj harakteristikoj dannogo soketa yavlyaetsya to, chto granicy zapisi dannyh predopredeleny.
Raw socket -
obespechivaet vozmozhnost' pol'zovatel'skogo dostupa k nizlezhashchim kommunikacionnym protokolam, podderzhivayushchim soket-abstrakcii. Takie sokety obychno yavlyayutsya datagram- orientirovannymi.
Funkciya socket sozdaet konechnuyu tochku dlya kommunikacij i vozvrashchaet fajlovyj deskriptor, ssylayushchijsya na soket, ili -1 v sluchae oshibki. Dannyj deskriptor ispol'zuetsya v dal'nejshem dlya ustanovleniya svyazi.

Dlya sozdaniya soketa tipa stream s protokolom TCP, obespechivayushchim kommunikacionnuyu podderzhku, vyzov funkcii socket dolzhen byt' sleduyushchim:

s = socket(AF_INET, SOCK_STREAM, 0);


Privyazka k lokal'nym imenam

Soket sozdaetsya bez imeni. Poka s soketom ne budet svyazano imya, udalennye processy ne imeyut vozmozhnosti ssylat'sya na nego i, sledovatel'no, na dannom sokete ne mozhet byt' polucheno nikakih soobshchenij. Kommunikacionnye processy ispol'zuyut dlya dannyh celej associacii. V Internet domene associaciya skladyvaetsya iz lokal'nogo i udalennogo adresa i iz lokal'nogo i udalennogo porta. V bol'shinstve domenov associaciya dolzhna byt' unikal'noj.

V Internet domene svyazyvanie soketa i imeni mozhet byt' ves'ma slozhnym, no, k schast'yu, obychno net neobhodimosti special'no privyazyvat' adres i nomer porta k soketu, tak kak funkcii connect i send avtomaticheski svyazhut dannyj soket s podhodyashchim adresom, esli eto ne bylo sdelano do ih vyzova.

Dlya svyazyvaniya soketa s adresom i nomerom porta ispol'zuyut sistemnyj vyzov bind:

bind(s, name, namelen);

Privyazyvaemoe imya (name) eto stroka bajt peremennoj dliny, kotoraya interpretiruetsya podderzhivaemym protokolom. Interpretaciya mozhet razlichat'sya v razlichnyh kommunikacionnyh domenah.


Ustanovlenie svyazi

So storony klienta svyaz' ustanavlivaetsya s pomoshch'yu standartnoj funkcii connect:

error = connect(s, serveraddr, serveraddrlen);

kotoraya iniciiruet ustanovlenie svyazi na sokete, ispol'zuya deskriptor soketa s i informaciyu iz struktury serveraddr, imeyushchej tip sockaddr_in, kotoraya soderzhit adres servera i nomer porta na kotoryj nado ustanovit' svyaz'. Esli soket ne byl svyazan s adresom, connect avtomaticheski vyzovet sistemnuyu funkciyu bind.

Connect vozvrashchaet 0, esli vyzov proshel uspeshno. Vozvrashchennaya velichina -1 ukazyvaet na to, chto v processe ustanovleniya svyazi proizoshla nekaya oshibka. V sluchae uspeshnogo vyzova funkcii process mozhet rabotat' s deskriptorom soketa, ispol'zuya funkcii read i write, i zakryvat' kanal ispol'zuya funkciyu close.

So storony servera process ustanovleniya svyazi slozhnee. Kogda server zhelaet predlozhit' odin iz svoih servisov, on svyazyvaet soket s obshcheizvestnym adresom, associiruyushchimsya s dannym servisom, i passivno slushaet etot soket. Dlya etih celej ispol'zuetsya sistemnyj vyzov listen:

error = listen(s, qlength);

gde s eto deskriptor soketa, a qlength eto maksimal'noe kolichestvo zaprosov na ustanovlenie svyazi, kotorye mogut stoyat' v ocheredi, ozhidaya obrabotki serverom; eto kolichestvo mozhet byt' ogranicheno osobennostyami sistemy.

Kogda server poluchaet zapros ot klienta i prinimaet reshenie ob ustanovlenii svyazi, on sozdaet novyj soket i svyazyvaet ego s associaciej, ekvivalentnoj 'slushayushchemu soketu'. Dlya Internet domena eto oznachaet tot zhe samyj nomer porta. Dlya etoj celi ispol'zuetsya sistemnyj vyzov accept:

newsock = accept(s, clientaddr, clientaddrlen);

Soket, associirovannyj klientom, i soket, kotoryj byl vozvrashchen funkciej accept, ispol'zuyutsya dlya ustanovleniya svyazi mezhdu serverom i klientom.

Process ustanovleniya svyazi pokazan na risunke 1.

IMAGE
Ris. 1: Vzaimodejstvie klienta i servera


Peredacha dannyh

Kogda svyaz' ustanovlena, s pomoshch'yu razlichnyh funkcij mozhet nachat'sya process peredachi dannyh. Pri nalichii svyazi, pol'zovatel' mozhet posylat' i poluchat' soobshcheniya s pomoshch'yu funkcij read i write:

write(s, buf, sizeof(buf)); read(s, buf, sizeof(buf));

Vyzovy send i recv prakticheski identichny read i write, za isklyucheniem togo, chto dobavlyaetsya argument flagov.

send(s, buf, sizeof(buf), flags); recv(s, buf, sizeof(buf), flags);

Mogut byt' ukazany odin ili bolee flagov s pomoshch'yu nenulevyh znachenij, takih, kak sleduyushchie:


Zakryvanie soketov

Kogda vzaimodejstvuyushchie moduli reshayut prekratit' peredachu dannyh i zakryt' seans svyazi, oni obmenivayutsya trehstoronnim rukopozhatiem s segmentami, soderzhashchimi ustanovlennyj bit "Ot otpravitelya bol'she net dannyh" (etot bit eshche nazyvaetsya FIN bit).

Esli soket bol'she ne ispol'zuetsya, process mozhet zakryt' ego s pomoshch'yu funkcii close, vyzvav ee s sootvetstvuyushchim deskriptorom soketa:

close(s);

Esli dannye byli associirovany s soketom, obeshchayushchim dostavku (soket tipa stream), sistema budet pytat'sya osushchestvit' peredachu etih dannyh. Tem ne menee, po istechenii dovol'no taki dlitel'nogo promezhutka vremeni, esli dannye vse eshche ne dostavleny, oni budut otbrosheny. Esli pol'zovatel'skij process zhelaet prekratit' lyubuyu peredachu dannyh, on mozhet sdelat' eto s pomoshch'yu vyzova shutdown na dannom sokete dlya ego zakrytiya. Vyzov shutdown vyzyvaet "momental'noe" otbrasyvanie vseh stoyashchih v ocheredi dannyh. Format vyzova sleduyushchij:

shutdown(s, how);

gde how imeet odno iz sleduyushchih znachenij:


Primer funkcii, dlya ustanovleniya WWW konnekcii

/*
-----------------------------------------------------------
  MakeConnection

  Function allocates a socket and estabishes a connection
  with remote host. Default port number 80.

  Input : WWW server name (with port number, if it is not 80)
  Output : file descriptor on success
              -1 on error

-----------------------------------------------------------
*/
int MakeConnection(unsigned char* ServerName){
  int s;
  struct sockaddr_in ssin;
  struct hostent* hp;
  int PortNum;
  unsigned char strHlp[STRNGLEN], *pch;

  /* use default port number - 80 or specific number from the
     server name */
  strcpy(strHlp,ServerName);
  pch = strchr(strHlp,':');
  if(pch==NULL){
    PortNum = 80;
  }else{
    pch[0] = '\0';
    pch++;
    PortNum = atoi(pch);
    if(PortNum==0){
      PortNum = 80;
    }
  }

  /* get host by name - resolve host name into IP address */
  if( (hp=gethostbyname(strHlp)) == NULL  )
  {
     return -1;
  }

  bzero(&ssin, sizeof(ssin));
  bcopy(hp->h_addr, &ssin.sin_addr, hp->h_length);
  ssin.sin_family = hp->h_addrtype;
  ssin.sin_port = htons(PortNum);

  /* allocate a socket */
  if((s=socket(AF_INET, SOCK_STREAM, 0))==-1)
  {
     return -1;
  }

  /* make a connection */
  if(connect(s, &ssin, sizeof(ssin), 0)==-1){

     return -1;
  }

  return s; /* socket descriptor */
}

Last-modified: Thu, 28 May 1998 14:26:10 GMT
Ocenite etot tekst: