А.В. Столяров - Введение в операционные системы (1114673), страница 28
Текст из файла (страница 28)
àäðåñ ñëóøàþùåãîñîêåòà, ñ êîòîðûì ìû õîòèì óñòàíîâèòü ñîåäèíåíèå). Åñòåñòâåííî, èñïîëüçóåòñÿ ïðè ýòîì ñòðóêòóðà òèïà, ñîîòâåòñòâóþùåãî èçáðàííîìó ñåìåéñòâó àäðåñàöèè (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).
Íà ìàøèíàõ, ïîðÿäîê áàéò â àðõèòåêòóðå êîòîðûõ ñîâïàäàåò ññåòåâûì, ýòè ôóíêöèè ïðîñòî âîçâðàùàþò ñâîé àðãóìåíò, â èíîì ñëó÷àå îíèïðîèçâîäÿò íåîáõîäèìûå ïðåîáðàçîâàíèÿ. Âîò ýòè ôóíêöèè:unsignedunsignedunsignedunsignedlong int htonl(unsigned long int hostlong);short int htons(unsigned short int hostshort);long int ntohl(unsigned long int netlong);short int ntohs(unsigned short int netshort);Êàê ìîæíî äîãàäàòüñÿ, áóêâà n â íàçâàíèÿõ ôóíêöèé îçíà÷àåò network (ò.å.ñåòåâîé ïîðÿäîê áàéò), áóêâà h − host (ïîðÿäîê áàéò äàííîé ìàøèíû). Íàêîíåö, s îáîçíà÷àåò êîðîòêèå öåëûå, à l − äëèííûå öåëûå ÷èñëà.
Òàêèì îáðàçîì, íàïðèìåð, ôóíêöèÿ ntohl() èñïîëüçóåòñÿ äëÿ ïðåîáðàçîâàíèÿ äëèííîãîöåëîãî èç ñåòåâîãî ïîðÿäêà áàéò â ïîðÿäîê áàéò, èñïîëüçóåìûé íà äàííîé ìàøèíå.×òî êàñàåòñÿ IP-àäðåñà, òî, èìåÿ åãî òåêñòîâîå ïðåäñòàâëåíèå (íàïðèìåð,ñòðîêó "192.168.10.12"), ìîæíî âîñïîëüçîâàòüñÿ ôóíêöèåé inet_aton()äëÿ ôîðìèðîâàíèÿ ñòðóêòóðû òèïà struct in_addr (ïîëå sin_addr ñòðóêòóðû sockaddr_in èìååò èìåííî ýòîò òèï):5 Òåðìèíûbig-endians è little-endians ââåäåíû Äæîíàòàíîì Ñâèôòîì â êíèãå Ïóòåøåñòâèÿ Ãóëëèâåðà äëÿ îáîçíà÷åíèÿ íåïðèìèðèìûõ ñòîðîííèêîâ ðàçáèâàíèÿ ÿèö, ñîîòâåòñòâåííî, ñ òóïîãî êîíöàè ñ îñòðîãî. Íà ðóññêèé ÿçûê ýòè íàçâàíèÿ îáû÷íî ïåðåâîäèëèñü êàê òóïîêîíå÷íèêè è îñòðîêîíå÷íèêè.
Àðãóìåíòû â ïîëüçó òîé èëè èíîé àðõèòåêòóðû äåéñòâèòåëüíî ÷àñòî íàïîìèíàþò ñâÿùåííóþ âîéíóîñòðîêîíå÷íèêîâ ñ òóïîêîíå÷íèêàìè.129int inet_aton(const char *cp, struct in_addr *inp);Çäåñü cp − ñòðîêà, ñîäåðæàùàÿ òåêñòîâîå ïðåäñòàâëåíèå IP-àäðåñà, à inp óêàçûâàåò íà ñòðóêòóðó, ïîäëåæàùóþ çàïîëíåíèþ. Ôóíêöèÿ âîçâðàùàåò íåíóëåâîå çíà÷åíèå, åñëè çàäàííàÿ ñòðîêà ÿâëÿåòñÿ äîïóñòèìîé òåêñòîâîé çàïèñüþIP-àäðåñà, è 0 â ïðîòèâíîì ñëó÷àå.Äîïóñòèì, íóæíûé íàì IP-àäðåñ ñîäåðæèòñÿ â ñòðîêå char *serv_ip, àïîðò − â ïåðåìåííîé port â âèäå öåëîãî ÷èñëà.
Òîãäà çàïîëíåíèå ñòðóêòóðûsockaddr_in ìîæåò âûãëÿäåòü òàê:struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);if(!inet_aton(serv_ip, &(addr.sin_addr))) {/* Îøèáêà - íåâàëèäíûé IP-àäðåñ */}Ïðè ñîçäàíèè ñëóøàþùåãî ñîêåòà íà ñåðâåðå çàäàâàòü êîíêðåòíûé ipàäðåñ íå îáÿçàòåëüíî, ãîðàçäî ïðîùå ïðîèíñòðóêòèðîâàòü ñèñòåìó ïðèíèìàòü ñîåäèíåíèÿ íà çàäàííûé ïîðò íà ëþáîì èç èìåþùèõñÿ â ñèñòåìå ipàäðåñîâ.
Ïðè ýòîì ïîëå sin_addr ñëåäóåò çàïîëíèòü ñïåöèàëüíûì çíà÷åíèåìINADDR_ANY:struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = INADDR_ANY;23.5.5Î çàëèïàíèè TCP-ïîðòà×àñòî ïðè ðàáîòå ñ ñåðâåðîì ìîæíî çàìåòèòü, ÷òî ïîñëå çàâåðøåíèÿ ïðîãðàììû-ñåðâåðàåå íåêîòîðîå âðåìÿ íåâîçìîæíî çàïóñòèòü ñ òåì æå çíà÷åíèåì íîìåðà ïîðòà.
Ýòî ïðîèñõîäèòîáû÷íî ïðè íåêîððåêòíîì çàâåðøåíèè ïðîãðàììû-ñåðâåðà, ëèáî åñëè ïðîãðàììà-ñåðâåð çàâåðøàåòñÿ ïðè àêòèâíûõ êëèåíòñêèõ ñîåäèíåíèÿõ.  ýòèõ ñëó÷àÿõ ÿäðî îïåðàöèîííîé ñèñòåìûíåêîòîðîå âðåìÿ ïðîäîëæàåò ñ÷èòàòü àäðåñ çàíÿòûì.Èçáåæàòü ýòèõ ñèòóàöèé ïðè îòëàäêå ïðîãðàììû-ñåðâåðà î÷åíü ñëîæíî, îäíàêî ñèñòåìàñîêåòîâ ïîçâîëÿåò èçìåíèòü ïîâåäåíèå ÿäðà â îòíîøåíèè àäðåñîâ, çàëèïøèõ ïîäîáíûìîáðàçîì.
Äëÿ ýòîãî íåîáõîäèìî ïåðåä âûçîâîìñîêåòå îïöèþSO_REUSEADDR.bind()âûñòàâèòü íà áóäóùåì ñëóøàþùåìÝòî äåëàåòñÿ ñ ïîìîùüþ ñèñòåìíîãî âûçîâàint setsockopt(int sd, int level, int optname,const void *optval, int optlen);130setsockopt():sdÏàðàìåòðçàäàåò äåñêðèïòîð ñîêåòà,levelîáîçíà÷àåò óðîâåíü (ñëîé) ñòåêà ïðîòîêîëîâ,ê êîòîðîìó èìååò îòíîøåíèå óñòàíàâëèâàåìàÿ îïöèÿ (â äàííîì ñëó÷àå ýòî óðîâåíü ñîêåòîâ,îáîçíà÷àåìûé êîíñòàíòîéSOL_SOCKET)Ïàðàìåòðoptnameçàäàåò èìÿ (íà ñàìîì äåëå,êîíå÷íî, ýòî íîìåð, èëè ÷èñëîâîé èäåíòèôèêàòîð) óñòàíàâëèâàåìîé îïöèè; â äàííîì ñëó÷àåíàì íóæíà îïöèÿSO_REUSEADDR.Ïîñêîëüêó èíôîðìàöèÿ, ñâÿçàííàÿ ñ íóæíîé îïöèåé, ìîæåò èìåòü ïðîèçâîëüíóþ ñëîæíîñòü, âûçîâ ïðèíèìàåò íåòèïèçèðîâàííûé óêàçàòåëü íà çíà÷åíèå îïöèè è äëèíó îïöèè (ïàðàìåòðû÷èñëî1,optvalèoptlenñîîòâåòñòâåííî).
Çíà÷åíèåì îïöèè â äàííîì ñëó÷àå áóäåò öåëîåòàê ÷òî ñëåäóåò çàâåñòè ïåðåìåííóþ òèïà int, ïðèñâîèòü åé çíà÷åíèåâ êà÷åñòâåoptvalàäðåñ ýòîé ïåðåìåííîé, à â êà÷åñòâåoptlen −âûðàæåíèå1 è ïåðåäàòüsizeof(int).Òàêèì îáðàçîì, íàø âûçîâ áóäåò âûãëÿäåòü òàê:int opt = 1;setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));23.6Èñïîëüçîâàíèå ñîêåòîâ äëÿ ñâÿçè ðîäñòâåííûõïðîöåññîâ îòëè÷èå îò íåèìåíîâàííûõ êàíàëîâ, ñîêåòû ïðåäñòàâëÿþò ñîáîé äâóíàïðàâëåííûé êàíàëñâÿçè, ÷òî äåëàåò èõ â íåêîòîðûõ ñëó÷àÿõ áîëåå óäîáíûì ñðåäñòâîì äàæå ïðè âçàèìîäåéñòâèèðîäñòâåííûõ ïðîöåññîâ. Îäíàêî ïðîöåäóðà óñòàíîâëåíèÿ ñîåäèíåíèÿ, ðàññìîòðåííàÿ âûøå,ïðåäñòàâëÿåòñÿ äëÿ òàêîé ñèòóàöèè ñëèøêîì ñëîæíîé.  ñâÿçè ñ ýòèì â ÎÑ Unix ïðåäóñìîòðåíâûçîâint socketpair(int af, int type, int protocol, int sv[2]);Ïàðàìåòðûaf, typeèprotocolçàäàþò, ñîîòâåòñòâåííî, ñåìåéñòâî àäðåñàöèè, òèï è ïðî-òîêîë äëÿ ñîçäàâàåìûõ ñîêåòîâ. Ñëåäóåò îòìåòèòü, ÷òî ìíîãèå ðåàëèçàöèè äîïóñêàþò ëèøüAF_UNIX, SOCK_STREAM è 0.
Ïàðàìåòð sv äîëæåí óêàçûòèïà int, â êîòîðûå âûçîâ çàíåñåò ôàéëîâûå äåñêðèïòîðûîäíó êîìáèíàöèþ ýòèõ ïàðàìåòðîâ:âàòü íà ìàññèâ èç äâóõ ýëåìåíòîâäâóõ ñîçäàííûõ ñîêåòîâ. Ñîêåòû ñîçäàþòñÿ óæå ñâÿçàííûìè äðóã ñ äðóãîì, ïðè÷åì îáà êîíöàîòêðûòû êàê íà ÷òåíèå, òàê è íà çàïèñü.Âûçîâ âîçâðàùàåò 0 â ñëó÷àå óñïåõà, -1 â ñëó÷àå îøèáêè.131Ëåêöèÿ 112424.1Ïðîáëåìà î÷åðåäíîñòè äåéñòâèé è åå ðåøåíèÿÑóòü ïðîáëåìûÍà ïðîøëîé ëåêöèè óïîìèíàëîñü, ÷òî ïðè ðàáîòå ñ ñîêåòàìè ïîòîêîâîãî òèïà ïîñëå ïðèíÿòèÿ ïåðâîãî ñîåäèíåíèÿ â ïðîãðàììå-ñåðâåðå âîçíèêàåòïðîáëåìà î÷åðåäíîñòè äåéñòâèé.
Ïîÿñíèì, â ÷åì îíà çàêëþ÷àåòñÿ.Ó íàñ èìåþòñÿ äâà äåñêðèïòîðà (à ïîñëå óñòàíîâëåíèÿ ñîåäèíåíèÿ ñ íîâûìè êëèåíòàìè èõ ÷èñëî âîçðàñòåò). Íà îäíîì èç äåñêðèïòîðîâ ìîæåò îæèäàòüçàïðîñ íà ñîåäèíåíèå íîâîãî êëèåíòà, êîòîðûé ïîòðåáóåò âûçîâà accept().Íî åñëè ìû ñäåëàåì accept(), à íèêàêîãî çàïðîñà íà ñîåäèíåíèå íå áûëî,íàøà ïðîãðàììà òàê è îñòàíåòñÿ âíóòðè âûçîâà accept(), ïðè÷åì ïðîáûòüòàì ìîæåò ñêîëü óãîäíî äîëãî: íèêòî âåäü íå ìîæåò ãàðàíòèðîâàòü, ÷òî êòîëèáî çàõî÷åò óñòàíîâèòü ñ íàìè íîâîå ñîåäèíåíèå.  ýòî âðåìÿ íà ëþáîé èçêëèåíòñêèõ ñîêåòîâ (òî åñòü ñîêåòîâ, îòâå÷àþùèõ çà ñîåäèíåíèå ñ êàæäûì èçêëèåíòîâ) ìîãóò ïðèéòè äàííûå, òðåáóþùèå îáðàáîòêè; ÿñíî, ÷òî, ïîêà ìûâèñèì âíóòðè âûçîâà accept(), íèêàêîé îáðàáîòêè äàííûõ íå ïðîèçîéäåò,ò.ê.