የሊኑክስ ኤፒአይ መጽሐፍ። አጠቃላይ መመሪያ »


የሊኑክስ ኤፒአይ መጽሐፍ። አጠቃላይ መመሪያ »

እንደምን አረፈድክ "Linux API" የሚለውን መጽሐፍ ወደ እርስዎ ትኩረት አመጣለሁ. አጠቃላይ መመሪያ "(የመጽሐፉ ትርጉም የሊኑክስ ፕሮግራሚንግ በይነገጽ). በአታሚው ድር ጣቢያ ላይ ሊታዘዝ ይችላል፣ እና የማስተዋወቂያ ኮዱን ከተገበሩ LinuxAPI 30% ቅናሽ ያገኛሉ።

ለግምገማ ከመጽሐፉ የተወሰደ፡-

ሶኬቶች፡ የአገልጋይ አርክቴክቸር

በዚህ ምእራፍ ውስጥ ተደጋጋሚ እና ትይዩ ሰርቨሮችን የመንደፍ መሰረታዊ መርሆችን እና እንዲሁም ከአገልጋይ ወገን የኢንተርኔት አፕሊኬሽኖች መፍጠርን የሚያመቻች ልዩ inetd ዴሞን እንነጋገራለን።

መደጋገም እና ትይዩ አገልጋዮች

ሁለት የተለመዱ ሶኬት ላይ የተመሰረቱ የአውታረ መረብ አገልጋይ አርክቴክቸር አሉ፡

  • ተደጋጋሚነት፡ አገልጋዩ ደንበኞችን አንድ በአንድ ያገለግላል፣ መጀመሪያ ከአንድ ደንበኛ የሚቀርብን ጥያቄ (ወይም ብዙ ጥያቄዎችን) በማስኬድ እና በመቀጠል ወደሚቀጥለው ይሄዳል።

  • ትይዩ፡ አገልጋዩ በአንድ ጊዜ ብዙ ደንበኞችን ለማገልገል የተነደፈ ነው።

ክፍል 44.8 አስቀድሞ በ FIFO ወረፋዎች ላይ የተመሰረተ የድግግሞሽ አገልጋይ ምሳሌ አቅርቧል።

የድግግሞሽ ሰርቨሮች ብዙውን ጊዜ የሚስማሙት የደንበኛ ጥያቄዎችን በአግባቡ በፍጥነት ማስተናገድ በሚቻልበት ሁኔታ ብቻ ነው፣ ምክንያቱም እያንዳንዱ ደንበኛ ከፊት ያሉት ሌሎች ደንበኞች እስኪቀርቡ ድረስ መጠበቅ ስላለበት ነው። ለዚህ አካሄድ የተለመደ የአጠቃቀም ጉዳይ በደንበኛ እና በአገልጋይ መካከል ነጠላ ጥያቄዎችን እና ምላሾችን መለዋወጥ ነው።

ትይዩ ሰርቨሮች እያንዳንዱ ጥያቄ ለማስኬድ ከፍተኛ ጊዜ የሚወስድ ከሆነ ወይም ደንበኛው እና አገልጋዩ ረጅም የመልእክት ልውውጥ በሚያደርጉበት ጊዜ ተስማሚ ናቸው። በዚህ ምእራፍ ላይ በዋናነት የምናተኩረው ትይዩ ሰርቨሮችን ለመንደፍ በባህላዊ (እና ቀላሉ) መንገድ ላይ ሲሆን ይህም ለእያንዳንዱ አዲስ ደንበኛ የተለየ የልጅ ሂደት መፍጠር ነው። እንዲህ ዓይነቱ ሂደት ደንበኛው የማገልገል ስራን በሙሉ ያከናውናል, ከዚያ በኋላ ያበቃል. እያንዳንዳቸው እነዚህ ሂደቶች በተናጥል የሚሰሩ ስለሆኑ ብዙ ደንበኞችን በተመሳሳይ ጊዜ ማገልገል ይችላሉ። የዋናው አገልጋይ ሂደት (ወላጅ) ዋና ተግባር ለእያንዳንዱ አዲስ ደንበኛ የተለየ ልጅ መፍጠር ነው (በአማራጭ ፣ ከሂደቶች ይልቅ ፣ የማስፈጸሚያ ክሮች መፍጠር ይችላሉ)።

በሚቀጥሉት ክፍሎች የኢንተርኔት ጎራ ሶኬቶችን መሰረት በማድረግ የተደጋገሙ እና ትይዩ አገልጋዮችን ምሳሌዎችን እንመለከታለን። እነዚህ ሁለት አገልጋዮች በደንበኛው የተላከውን ማንኛውንም መልእክት ቅጂ የሚመልስ ቀለል ያለ የ echo አገልግሎትን (RFC 862) ይተገብራሉ።

echo ተደጋጋሚ udp አገልጋይ

በዚህ እና በሚቀጥለው ክፍል ለማሚቶ አገልግሎት አገልጋዮችን እናስተዋውቃለን። በወደብ ቁጥር 7 ላይ ይገኛል እና በሁለቱም በ UDP እና TCP ላይ ይሰራል (ይህ ወደብ የተጠበቀ ነው, እና ስለዚህ የማሚቶ አገልጋይ ከአስተዳዳሪ መብቶች ጋር መከናወን አለበት).

የማስተጋባት UDP አገልጋይ ዳታግራሞችን ያለማቋረጥ ያነባል እና የእነሱን ቅጂ ወደ ላኪው ይመልሳል። አገልጋዩ በአንድ ጊዜ አንድ መልእክት ብቻ ማስተናገድ ስለሚያስፈልገው፣ ተደጋጋሚ አርክቴክቸር እዚህ በቂ ይሆናል። የአገልጋዮች ራስጌ ፋይል በዝርዝሩ 56.1-XNUMX ውስጥ ይታያል።

ዝርዝር 56.1. የራስጌ ፋይል ለፕሮግራሞች id_echo_sv.c እና id_echo_cl.c

# "inet_sockets.h"ን ይጨምራል /* የሶኬት ተግባራችንን ያውጃል */
# "tlpi_hdr.h"ን ያካትቱ

#SERVICE "echo" /* UDP አገልግሎት ስምን ይግለጹ */

#BUF_SIZE 500 ን ይግለጹ /* ከፍተኛውን የዳታግራም መጠን
በደንበኛው እና በአገልጋይ ሊነበብ ይችላል */
__________________________________________________________________ ሶኬቶች/id_echo.h

56.2-XNUMX መዘርዘር የአገልጋይ አተገባበርን ያሳያል። የሚከተሉትን ነጥቦች ልብ ማለት ተገቢ ነው.

  • አገልጋዩን ወደ ዴሞን ሁነታ ለማስቀመጥ ከክፍል 37.2 የቤይዳሞን () ተግባርን እንጠቀማለን ።

  • መርሃግብሩ የበለጠ የታመቀ እንዲሆን በክፍል 55.12 የተገነባውን የበይነመረብ ጎራ ሶኬት ቤተ-መጽሐፍትን እንጠቀማለን ።

  • አገልጋዩ ለደንበኛው ምላሹን መመለስ ካልቻለ የ syslog() ጥሪን በመጠቀም ወደ ምዝግብ ማስታወሻው መልእክት ይጽፋል።

በእውነተኛ አፕሊኬሽን syslog() በመጠቀም የምዝግብ ማስታወሻ ድግግሞሽ ላይ የተወሰነ ገደብ እንጥላለን። ይህ አጥቂ የስርዓት ምዝግብ ማስታወሻውን የመሙላት እድል ያስወግዳል። እንዲሁም እያንዳንዱ የ syslog() ጥሪ በነባሪ fsync () ስለሚጠቀም በጣም ውድ እንደሆነ ያስታውሱ።

ዝርዝር 56.2. የማስተጋባት UDP አገልግሎትን የሚተገብር ተደጋጋሚ አገልጋይ

__________________________________________________ሶኬቶች/id_echo_sv.c
#ያካትቱ
# "id_echo.h"ን ያካትቱ
#ያካትተው "ዳሞን_ሁን.h"

int
ዋና (int argc፣ char *argv[])
{
int sfd;
መጠን_ት numRead;
socklen_tlen;
መዋቅር sockaddr_storage claddr;
ቻርቡፍ[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

ከሆነ (ዴሞን (0) == -1)
errExit ("Daemon መሆን");

sfd = inetBind (አገልግሎት፣ SOCK_DGRAM፣ NULL);
ከሆነ (ኤስኤፍዲ == -1) {
syslog(LOG_ERR፣ "የአገልጋይ ሶኬት (%s) መፍጠር አልተቻለም"፣
ስትሮር (ኤርኖ));
መውጣት(EXIT_FAILURE);

/* ዳታግራም ይቀበሉ እና ቅጂዎችን ወደ ላኪዎች ይመልሱ */
}
ለ(;;) {
ሌንስ = የመጠን (የመዋቅር sockaddr_storage);
numRead = recvfrom (sfd, buf, BUF_SIZE, 0, (struct sockaddr *) & claddr, &len);

ከሆነ (ቁጥር == -1)
errExit ("recvfrom");
ከሆነ (sendto (sfd, buf, numRead, 0, (የተዋቀረ sockaddr *) & claddr, len)
=numRead)
syslog(LOG_WARNING፣ "ለ%s (%s) ምላሽ በማስተጋባት ላይ ስህተት"፣
inetAddressStr((መዋቅር sockaddr *) &claddr፣ ሌንስ፣
addrStr፣ IS_ADDR_STR_LEN)፣
ስትሮር (ኤርኖ));
}
}
__________________________________________________ሶኬቶች/id_echo_sv.c

አገልጋዩን ለመፈተሽ ፕሮግራሙን በ 56.3 ዝርዝር ውስጥ እንጠቀማለን. እንዲሁም በክፍል 55.12 የተሰራውን የኢንተርኔት ጎራ ሶኬት ቤተመፃህፍት ይጠቀማል። የደንበኛው ፕሮግራም አገልጋዩ የሚገኝበትን የአውታረ መረብ አስተናጋጅ ስም በትእዛዝ መስመር ላይ እንደ መጀመሪያው ክርክር ይወስዳል። ደንበኛው እያንዳንዱን የቀረውን ክርክሮች ወደ አገልጋዩ እንደ የተለየ ዳታግራም የሚልክበት loop ያስገባል እና ከዚያ አንብቦ ከአገልጋዩ የተቀበሉትን ዳታግራም በምላሹ ያወጣል።

ዝርዝር 56.3. ለ echo UDP አገልግሎት ደንበኛ

# "id_echo.h"ን ያካትቱ

int
ዋና (int argc፣ char *argv[])
{
int sfd,j;
መጠን_tlen;
መጠን_ት numRead;
ቻርቡፍ[BUF_SIZE];

ከሆነ (argc < 2 || strcmp(argv[1], "--እርዳታ") == 0)
usageErr("%s አስተናጋጅ msg…n", argv[0]);

/* በመጀመሪያው የትእዛዝ መስመር ክርክር ላይ በመመስረት የአገልጋዩን አድራሻ ይፍጠሩ */
sfd = inetConnect(argv [1]፣ SERVICE፣ SOCK_DGRAM);
ከሆነ (ኤስኤፍዲ == -1)
ገዳይ ("ከአገልጋይ ሶኬት ጋር መገናኘት አልተቻለም");

/* የተቀሩትን ክርክሮች ወደ አገልጋዩ እንደ የተለየ ዳታግራም ይላኩ */
ለ (j = 2; j < argc; j++) {
ሌንስ = strlen (argv [j]);
ከሆነ (ጻፍ(sfd፣ argv[j]፣ len) != len)
ገዳይ ("ከፊል / ያልተሳካ ጽሑፍ");

numRead = ማንበብ (sfd, buf, BUF_SIZE);
ከሆነ (ቁጥር == -1)
errExit ("አንብብ");
printf("[%ld ባይት] %*sn"፣ (ረዥም) numRead፣ (int) numRead፣ buf)
}
መውጣት(EXIT_SUCCESS);
}
__________________________________________________ሶኬቶች/id_echo_cl.c

የሚከተለው አገልጋዩን ስንጀምር የምናየው ምሳሌ እና ሁለት የደንበኛ አጋጣሚዎች ነው።

$ su // ከተያዘ ወደብ ጋር ለመያያዝ ልዩ መብቶችን ይፈልጋል
የይለፍ ቃል:
# ./id_echo_sv // አገልጋዩ ወደ ዳራ ይሄዳል
# ውጣ // የአስተዳዳሪ መብቶችን ተወው
$ ./id_echo_cl localhost hello world // ይህ ደንበኛ ሁለት ዳታግራም ይልካል
[5 ባይት] ሰላም // ደንበኛው ከአገልጋዩ የተቀበለውን ምላሽ ያወጣል።
(5 ባይት) ዓለም
$ ./id_echo_cl localhost ደህና ሁን // ይህ ደንበኛ አንድ ዳታግራም ይልካል
[7 ባይት] ደህና ሁን

አስደሳች ንባብ እመኛለሁ)

ምንጭ: linux.org.ru