А.В. Столяров - Введение в операционные системы (1152218), страница 28
Текст из файла (страница 28)
Æåëàòåëüíî ñâÿçàòü ñîêåò ñ êîíêðåòíûì àäðåñîì ñ ïîìîùüþ bind(), â ïðîòèâíîì ñëó÷àå ñ ñîêåòà ìîæíî áóäåò îòïðàâëÿòüäàííûå (ñèñòåìà ñàìà âûáåðåò îäèí èç ñâîèõ àäðåñîâ è ïîðòîâ â êà÷åñòâåàäðåñà îòïðàâèòåëÿ), íî íå áóäåò âîçìîæíîñòè ïîëó÷èòü îòâåò.Ïîñëå òîãî, êàê ñîêåò ñîçäàí è ñâÿçàí ñ àäðåñîì, äëÿ ïåðåäà÷è è ïðèåìàäàííûõ ìîæíî èñïîëüçîâàòü ñèñòåìíûå âûçîâû sendto() è recvfrom():3 Íàçâàíèåôóíêöèè htons() ïîëó÷åíî êàê ñîêðàùåíèå îò Host to Network Short, ò.å. ïðåîáðàçîâàíèå èçõîñòîâîãî â ñåòåâîé ïîðÿäîê áàéò äëÿ êîðîòêîãî öåëîãî. Áîëåå ïîäðîáíî ïîíÿòèå ñåòåâîãî ïîðÿäêà áàéòáóäåò ðàññìîòðåíî íèæå.124int sendto(int s, const void *buf, int len, int flags,const struct sockaddr *to, socklen_t tolen);int recvfrom(int s, void *buf, int len, int flags,struct sockaddr *from, socklen_t *fromlen); îáîèõ âûçîâàõ ïàðàìåòð s çàäàåò äåñêðèïòîð ñîêåòà, buf óêàçûâàåò íàáóôåð, ñîäåðæàùèé äàííûå äëÿ ïåðåäà÷è ëèáî ïðåäíàçíà÷åííûé äëÿ ðàçìåùåíèÿ ïðèíÿòûõ äàííûõ, len óñòàíàâëèâàåò ðàçìåð ýòîãî áóôåðà (ñîîòâåòñòâåííî, êîëè÷åñòâî äàííûõ, ïîäëåæàùèõ ïðèåìó èëè ïåðåäà÷å).
Ïàðàìåòðflags èñïîëüçóåòñÿ äëÿ óêàçàíèÿ äîïîëíèòåëüíûõ îïöèé; äëÿ íîðìàëüíîéðàáîòû îáû÷íî äîñòàòî÷íî óêàçàòü çíà÷åíèå 0. âûçîâå sendto() ïàðàìåòð to óêàçûâàåò íà ñòðóêòóðó, ñîäåðæàùóþàäðåñ ñîêåòà, íà êîòîðûé íåîáõîäèìî îòïðàâèòü äàííûå (òî åñòü àäðåñ ïîëó÷àòåëÿ ñîîáùåíèÿ).
ßñíî, ÷òî èñïîëüçóåòñÿ ïðè ýòîì ñòðóêòóðà òèïà, ñîîòâåòñòâóþùåãî èçáðàííîìó ñåìåéñòâó àäðåñàöèè (sockaddr_in äëÿ AF_INET èsockaddr_un äëÿ AF_UNIX). Ïàðàìåòð tolen äîëæåí áûòü ðàâåí ðàçìåðó ýòîéñòðóêòóðû. Òèï socklen_t îáû÷íî ÿâëÿåòñÿ ñèíîíèìîì òèïà int. âûçîâå recvfrom() ïàðàìåòð from óêàçûâàåò íà ñòðóêòóðó, â êîòîðóþâûçîâó ñëåäóåò çàïèñàòü àäðåñ îòïðàâèòåëÿ ïîëó÷åííîãî ïàêåòà (ò.å. òàêèìîáðàçîì ìîæíî óçíàòü, îòêóäà ïàêåò ïðèøåë).
Ïàðàìåòð fromlen ïðåäñòàâëÿåò ñîáîé óêàçàòåëü íà ïåðåìåííóþ òèïà socklen_t, ïðè÷åì ïåðåä âûçîâîìrecvfrom() â ýòó ïåðåìåííóþ ñëåäóåò çàíåñòè ðàçìåð àäðåñíîé ñòðóêòóðû,íà êîòîðóþ óêàçûâàåò ïðåäûäóùèé ïàðàìåòð; ïîñëå âîçâðàòà èç recvfrom()ïåðåìåííàÿ áóäåò ñîäåðæàòü êîëè÷åñòâî áàéò, êîòîðûå âûçîâ â èòîãå â ýòóñòðóêòóðó çàïèñàë.Ñëåäóåò îòìåòèòü, ÷òî ïðè ðàáîòå ïî ñåòè Èíòåðíåò äëÿ ïåðåäà÷è äåéòàãðàìì èñïîëüçóåòñÿ ïðîòîêîë UDP. Îñîáåííîñòè ñâÿçêè IP/UDP òàêîâû, ÷òî ïåðåäàí ìîæåò áûòü òîëüêî ïàêåòîãðàíè÷åííîãî ðàçìåðà, ïðè÷åì êîíêðåòíûé ðàçìåð, âîîáùå ãîâîðÿ, ìîæåò îêàçàòüñÿ ðàçëè÷íûì äëÿ ðàçëè÷íûõ àäðåñîâ ïîëó÷àòåëåé.
Èòîãîì ýòîãî îáñòîÿòåëüñòâà ÿâëÿþòñÿ äîñòàòî÷íîñëîæíûå ïðîöåäóðû äèíàìè÷åñêîãî îïðåäåëåíèÿ äîïóñòèìîãî ðàçìåðà ïàêåòà; îïèñàíèå ýòèõïðîöåäóð âûõîäèò çà ðàìêè íàøåãî êóðñà. Ïðè æåëàíèè ÷èòàòåëü ìîæåò ñàìîñòîÿòåëüíî èçó÷èòü èõ, îáðàòèâøèñü, íàïðèìåð, ê êíèãå [6].23.5Ïîòîêîâûå ñîêåòû. Êëèåíò-ñåðâåðíàÿ ìîäåëüÏðè âçàèìîäåéñòâèè ñ ïîìîùüþ ïîòîêîâûõ ñîêåòîâ íåîáõîäèìî ïåðåä íà÷àëîì âçàèìîäåéñòâèÿ óñòàíîâèòü ñîåäèíåíèå. ßñíî, ÷òî åñëè ðå÷ü èäåò îâçàèìîäåéñòâèè íåðîäñòâåííûõ ïðîöåññîâ, è òåì áîëåå î âçàèìîäåéñòâèè ïðîöåññîâ, íàõîäÿùèõñÿ íà ðàçíûõ ìàøèíàõ, îäèí èç ó÷àñòíèêîâ âçàèìîäåéñòâèÿäîëæåí áûòü èíèöèàòîðîì ñîåäèíåíèÿ, à âòîðîé − ïðèíÿòü ñîåäèíåíèå (ñîãëàñèòüñÿ íà åãî óñòàíîâëåíèå).125запрос соединенияLСерверLКлиентСерверииненсоедеКлиентÐèñ.
23: Óñòàíîâëåíèå ñîåäèíåíèÿ ìåæäó ïîòîêîâûìè ñîêåòàìèÇäåñü ìû ñòàëêèâàåìñÿ ñ ïîíÿòèÿìè êëèåíòà è ñåðâåðà. Ïîä ñåðâå-ïîíèìàåòñÿ ïðîãðàììà, îæèäàþùàÿ çàïðîñîâ è ïðîèçâîäÿùàÿêàêèå-ëèáî äåéñòâèÿ èñêëþ÷èòåëüíî â îòâåò íà çàïðîñû, à ïðè îòñóòñòâèè çàïðîñîâ íå äåëàþùàÿ âîîáùå íè÷åãî. Ñîîòâåòñòâåííî,ïîä êëèåíòîì ïîíèìàåòñÿ ïðîãðàììà, îáðàùàþùàÿñÿ ñ çàïðîñîìê ñåðâåðó4 .ðîìÏðè óñòàíîâëåíèè ñîåäèíåíèÿ ìåæäó ïîòîêîâûìè ñîêåòàìè îäèí ïðîöåññîæèäàåò çàïðîñà íà óñòàíîâëåíèå ñîåäèíåíèÿ, à äðóãîé èíèöèèðóåò òàêîé çàïðîñ. Ýòè ïðîöåññû è íàçûâàþòñÿ ñ òî÷êè çðåíèÿ óñòàíîâëåíèÿ ñîåäèíåíèÿñåðâåðîì è êëèåíòîì; â ÷àñòíîñòè, ïðè ðàáîòå ïî ñåòè Èíòåðíåò äëÿ îðãàíèçàöèè âçàèìîäåéñòâèÿ ïîòîêîâûõ ñîêåòîâ èñïîëüçóåòñÿ ïðîòîêîë TCP, àñîîòâåòñòâóþùèå ïðîãðàììû íàçûâàþòñÿ TCP-ñåðâåðîì è TCP-êëèåíòîì.23.5.1Îðãàíèçàöèÿ ñåðâåðà×òîáû íà÷àòü îæèäàíèå çàïðîñîâ íà ñîåäèíåíèå, ñåðâåð ñîçäàåò ñîêåò ñîîòâåòñòâóþùåãî òèïà, ñâÿçûâàåò åãî ñ àäðåñîì è ïåðåâîäèò â ñïåöèàëüíîåñîñòîÿíèå, íàçûâàåìîå ñëóøàþùèì (àíãë.
listening). Íà ñîêåòå, íàõîäÿùåìñÿâ ñëóøàþùåì ñîñòîÿíèè, ìîæåò áûòü îñóùåñòâëåíà òîëüêî îäíà îïåðàöèÿ −ïðèíÿòèå ñîåäèíåíèÿ. Ïðè óñòàíîâëåíèè ñîåäèíåíèÿ ÿäðî îïåðàöèîííîé ñèñòåìû, êîòîðàÿ îáñëóæèâàåò ïðîãðàììó-ñåðâåð, ñîçäàåò åùå îäèí ñîêåò, êîòîðûé è áóäåò èñïîëüçîâàòüñÿ äëÿ ïåðåäà÷è äàííûõ ïî òîëüêî ÷òî óñòàíîâëåííîìó ñîåäèíåíèþ (ðèñ.
23).Èòàê, íà ñòîðîíå ñåðâåðà ñîêåò íåîáõîäèìî ñîçäàòü âûçîâîì socket() ññîîòâåòñòâóþùèìè ïàðàìåòðàìè è ñâÿçàòü åãî ñ êîíêðåòíûì àäðåñîì, íà êîòîðîì áóäóò ïðèíèìàòüñÿ ñîåäèíåíèÿ, ñ ïîìîùüþ âûçîâà bind(). Çàòåì ñîêåòñëåäóåò ïåðåâåñòè â ñëóøàþùèé ðåæèì (íà ðèñ. 23 ñëóøàþùèé ñîêåò îáîçíà÷åí áóêâîé L) ñ ïîìîùüþ âûçîâà4 Âîîáùåãîâîðÿ, îäíà è òà æå ïðîãðàììà ìîæåò âûïîëíÿòü ôóíêöèè ñåðâåðà ïî îòíîøåíèþ ê îäíèìïðîãðàììàì è êëèåíòà − ïî îòíîøåíèþ ê äðóãèì, åñëè äëÿ óäîâëåòâîðåíèÿ çàïðîñà êëèåíòà ñåðâåðóíåîáõîäèìî âîñïîëüçîâàòüñÿ óñëóãàìè äðóãîãî ñåðâåðà126int listen(int sd, int qlen);Ïàðàìåòð sd − ñâÿçàííûé ñ ñîêåòîì ôàéëîâûé äåñêðèïòîð.
Ïàðàìåòð qlençàäàåò ðàçìåð î÷åðåäè íåïðèíÿòûõ çàïðîñîâ íà ñîåäèíåíèå. Ïîÿñíèì ýòî. Äîïóñòèì, ìû ïåðåâåëè ñîêåò â ñëóøàþùèé ðåæèì, è íåñêîëüêî êëèåíòîâ óæåîòïðàâèëè íàì çàïðîñû íà ñîåäèíåíèå, íî â ñèëó òåõ èëè èíûõ ïðè÷èí ìûíåêîòîðîå âðåìÿ íå ïðèíèìàåì ýòè çàïðîñû (òî åñòü íå âûïîëíÿåì ñîîòâåòñòâóþùóþ îïåðàöèþ ñî ñëóøàþùèì ñîêåòîì). Âîçìîæíîñòè ñèñòåìû ïî õðàíåíèþ íåîáðàáîòàííûõ çàïðîñîâ îãðàíè÷åíû. Ïåðâûå qlen çàïðîñîâ áóäóòîæèäàòü ïðèíÿòèÿ ñîåäèíåíèÿ, åñëè æå ñèñòåìà ïîëó÷èò åùå çàïðîñû, îíèáóäóò îòêëîíåíû. Ñëåäóåò îñîáî ïîä÷åðêíóòü, ÷òî ïàðàìåòð qlen íå èìååòíèêàêîãî îòíîøåíèÿ ê îáùåìó êîëè÷åñòâó ñîåäèíåíèé ñ êëèåíòàìè.
Îáû÷íî â êà÷åñòâå ïàðàìåòðà qlen ïåðåäàþò ÷èñëî 5, ïîñêîëüêó íåêîòîðûå ÿäðàîïåðàöèîííûõ ñèñòåì íå ïîçâîëÿþò ñîçäàâàòü î÷åðåäü áîëüøåãî ðàçìåðà, àìåíüøàÿ î÷åðåäü ìîæåò îêàçàòüñÿ íåäîñòàòî÷íîé.Ïðèíÿòèå ñîåäèíåíèÿ ïðîèçâîäèòñÿ âûçîâîìint accept(int sd, struct sockaddr *addr, socklen_t *addrlen);Ïàðàìåòð sd çàäàåò äåñêðèïòîð ñëóøàþùåãî ñîêåòà.
Ïàðàìåòð addr óêàçûâàåò íà ñòðóêòóðó, â êîòîðóþ ñëåäóåò çàïèñàòü àäðåñ ñîêåòà, ñ êîòîðûì óñòàíîâëåíî ñîåäèíåíèå (èíà÷å ãîâîðÿ, àäðåñ äðóãîãî êîíöà ñîåäèíåíèÿ). Ïàðàìåòðaddrlen ïðåäñòàâëÿåò ñîáîé óêàçàòåëü íà ïåðåìåííóþ òèïà socklen_t, ïðè÷åì ïåðåä âûçîâîì accept() â ýòó ïåðåìåííóþ ñëåäóåò çàíåñòè ðàçìåð àäðåñíîé ñòðóêòóðû, íà êîòîðóþ óêàçûâàåò ïðåäûäóùèé ïàðàìåòð; ïîñëå âîçâðàòàèç accept() ïåðåìåííàÿ áóäåò ñîäåðæàòü êîëè÷åñòâî áàéò, êîòîðûå âûçîâ âèòîãå â ýòó ñòðóêòóðó çàïèñàë. Ýòî àíàëîãè÷íî ïàðàìåòðàì from è fromlenâ âûçîâå recvfrom().Âûçîâ accept() âîçâðàùàåò ôàéëîâûé äåñêðèïòîð íîâîãî ñîêåòà, ñîçäàííîãî ñïåöèàëüíî äëÿ îáñëóæèâàíèÿ âíîâü óñòàíîâëåííîãî ñîåäèíåíèÿ (ëèáî-1 â ñëó÷àå îøèáêè). Åñëè íà ìîìåíò âûïîëíåíèÿ accept() çàïðîñîâ íà ñîåäèíåíèå åùå íå ïîñòóïèëî, âûçîâ áëîêèðóåò âûçâàâøèé ïðîöåññ è îæèäàåòïîñòóïëåíèÿ çàïðîñà íà ñîåäèíåíèå, âîçâðàùàÿ óïðàâëåíèå òîëüêî ïîñëå òîãî,êàê òàêîé çàïðîñ ïîñòóïèò, è ñîåäèíåíèå áóäåò óñòàíîâëåíî.Ñëåäóåò îòìåòèòü, ÷òî ñ ìîìåíòà ïðèíÿòèÿ ïåðâîãî ñîåäèíåíèÿ âïðîãðàììå-ñåðâåðå èìååòñÿ äâà äåñêðèïòîðà, òðåáóþùèõ îáðàáîòêè: äåñêðèïòîð ñëóøàþùåãî ñîêåòà, íà êîòîðîì ìîæíî ïðèíèìàòü íîâûå çàïðîñû íà ñîåäèíåíèÿ, è ñîêåò, ñîîòâåòñòâóþùèé ïðèíÿòîìó ñîåäèíåíèþ, ñ êîòîðîãî òðåáóåòñÿ ÷èòàòü ïðèøåäøèå îò êëèåíòà äàííûå (íàïðèìåð, òåêñò çàïðîñà).
Ýòîñîçäàåò ïðîáëåìó î÷åðåäíîñòè äàëüíåéøèõ äåéñòâèé. Ìû âåðíåìñÿ ê îáñóæäåíèþ ýòîé ïðîáëåìû íà ñëåäóþùåé ëåêöèè.12723.5.2Îðãàíèçàöèÿ êëèåíòàÊëèåíòñêàÿ ïðîãðàììà äîëæíà, êàê è ñåðâåð, ñîçäàòü ñîêåò âûçîâîìsocket(). Ñâÿçûâàòü ñîêåò ñ êîíêðåòíûì àäðåñîì íå îáÿçàòåëüíî; åñëè ýòîãîíå ñäåëàòü, ñèñòåìà âûáåðåò àäðåñ àâòîìàòè÷åñêè.Çàïðîñ íà ñîåäèíåíèå ôîðìèðóåòñÿ âûçîâîìint connect(int sd, struct sockaddr *addr, int addrlen);Ïàðàìåòð sd − ñâÿçàííûé ñ ñîêåòîì ôàéëîâûé äåñêðèïòîð. Ïàðàìåòð addróêàçûâàåò íà ñòðóêòóðó, ñîäåðæàùóþ àäðåñ ñåðâåðà (ò.å. àäðåñ ñëóøàþùåãîñîêåòà, ñ êîòîðûì ìû õîòèì óñòàíîâèòü ñîåäèíåíèå). Åñòåñòâåííî, èñïîëüçóåòñÿ ïðè ýòîì ñòðóêòóðà òèïà, ñîîòâåòñòâóþùåãî èçáðàííîìó ñåìåéñòâó àäðåñàöèè (sockaddr_in äëÿ AF_INET è sockaddr_un äëÿ AF_UNIX).
Ïàðàìåòðaddrlen äîëæåí áûòü ðàâåí ðàçìåðó ýòîé ñòðóêòóðû.Âûçîâ âîçâðàùàåò 0 â ñëó÷àå óñïåõà, -1 â ñëó÷àå îøèáêè.23.5.3Îáìåí äàííûìèÏîñëå óñïåøíîãî óñòàíîâëåíèÿ ñîåäèíåíèÿ äëÿ ïåðåäà÷è ïî íåìó äàííûõìîæíî èñïîëüçîâàòü óæå èçâåñòíûå íàì âûçîâû read() è write(), ñ÷èòàÿäåñêðèïòîðû ñîåäèíåííûõ ñîêåòîâ îáû÷íûìè ôàéëîâûìè äåñêðèïòîðàìè (íàñòîðîíå ñåðâåðà ýòî äåñêðèïòîð, âîçâðàùåííûé âûçîâîì accept(), íà ñòîðîíåêëèåíòà − äåñêðèïòîð ñîêåòà, ê êîòîðîìó ïðèìåíÿëñÿ âûçîâ connect()).Äëÿ áîëåå ãèáêîãî óïðàâëåíèÿ îáìåíîì äàííûìè ñóùåñòâóþò òàêæå âûçîâû recv() èsend(), îòëè÷àþùèåñÿ îò read() è write() òîëüêî íàëè÷èåì äîïîëíèòåëüíîãî ïàðàìåòðàflags. Ïðè æåëàíèè ÷èòàòåëü ìîæåò îçíàêîìèòüñÿ ñ ýòèìè âûçîâàìè ñàìîñòîÿòåëüíî, âîñïîëüçîâàâøèñü êîìàíäîé man â ÎÑ Unix èëè êíèãàìè [2] è [6].Çàâåðøèòü ðàáîòó ñ ñîêåòîì ìîæíî ñ ïîìîùüþ âûçîâàint shutdown(int sd, int how);Ïàðàìåòð sd çàäàåò äåñêðèïòîð ñîêåòà, how − ÷òî èìåííî ñëåäóåò ïðåêðàòèòü.Ïðè how == 0 ñîêåò çàêðûâàåòñÿ íà ÷òåíèå, ïðè how == 1 − íà çàïèñü, ïðèhow == 2 − ïîëíîñòüþ (â îáà íàïðàâëåíèÿ).Ìîæíî òàêæå ïðîñòî çàêðûòü äåñêðèïòîð ñîêåòà ñ ïîìîùüþ âûçîâàclose().
Ñäåëàòü ýòî ñëåäóåò â ëþáîì ñëó÷àå, ò.ê. shutdown() òîëüêî ïðåêðàùàåò îáìåí äàííûìè íà ñîêåòå, íî ñàì ñîêåò (è åãî ôàéëîâûé äåñêðèïòîð)ïðè ýòîì íå èñ÷åçàþò, à êîëè÷åñòâî îäíîâðåìåííî îòêðûòûõ ôàéëîâûõ äåñêðèïòîðîâ â ñèñòåìå îãðàíè÷åíî. ñëó÷àå, åñëè äàëüíèé êîíåö ñîåäèíåíèÿ çàêðûò, î÷åðåäíîé âûçîâ read()èëè recv() âåðíåò 0, ñèãíàëèçèðóÿ î êîíöå ôàéëà.12823.5.4Ïîäðîáíåå îá àäðåñàõ â AF_INETÏðè îïèñàíèè ñòðóêòóðû sockaddr_in óïîìèíàëàñü íåîáõîäèìîñòü ïðåîáðàçîâàíèÿ ïîðÿäêà áàéò ïðè çàïîëíåíèè ïîëÿ sin_port. Ðàññìîòðèì ýòîòâîïðîñ ïîäðîáíåå.Ïîðÿäîê áàéò â ïðåäñòàâëåíèè öåëûõ ÷èñåë â ïàìÿòè ìîæåò âàðüèðîâàòüñÿ îò îäíîé àðõèòåêòóðû ê äðóãîé. Àðõèòåêòóðû, â êîòîðûõ ñòàðøèé áàéò÷èñëà èìååò íàèìåíüøèé àäðåñ (èíà÷å ãîâîðÿ, áàéòû ðàñïîëîæåíû â ïðÿìîìïîðÿäêå), â àíãëîÿçû÷íîé ëèòåðàòóðå îáîçíà÷àþòñÿ òåðìèíîì big-endian, ààðõèòåêòóðû, â êîòîðûõ íàèìåíüøèé àäðåñ èìååò ìëàäøèé áàéò, òî åñòü ïîðÿäîê áàéòîâ îáðàòíûé, − little-endian5 .×òîáû ñäåëàòü âîçìîæíûì âçàèìîäåéñòâèå ïî ñåòè ìåæäó ìàøèíàìè,èìåþùèìè ðàçíûå àðõèòåêòóðû, ïðèíÿòî ñîãëàøåíèå, ÷òî ïåðåäà÷à öåëî÷èñëåííîé èíôîðìàöèè ïî ñåòè âñåãäà èäåò â ïðÿìîì (big-endian) ïîðÿäêå áàéò,ò.å.
ñòàðøèé áàéò ïåðåäàåòñÿ ïåðâûì. ×òîáû îáåñïå÷èòü ïåðåíîñèìîñòü ïðîãðàìì íà óðîâíå èñõîäíîãî êîäà, â îïåðàöèîííûõ ñèñòåìàõ ñåìåéñòâà Unixââåäåíû ñòàíäàðòíûå áèáëèîòå÷íûõ ôóíêöèè äëÿ ïðåîáðàçîâàíèÿ öåëûõ ÷èñåë èç ôîðìàòà äàííîé ìàøèíû (host byte order) â ñåòåâîé ôîðìàò (networkbyte order). Íà ìàøèíàõ, ïîðÿäîê áàéò â àðõèòåêòóðå êîòîðûõ ñîâïàäàåò ññåòåâûì, ýòè ôóíêöèè ïðîñòî âîçâðàùàþò ñâîé àðãóìåíò, â èíîì ñëó÷àå îíèïðîèçâîäÿò íåîáõîäèìûå ïðåîáðàçîâàíèÿ.