Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π² срСдС Linux. Π’Ρ‚ΠΎΡ€ΠΎΠ΅ ΠΈΠ·Π΄Π°Π½ΠΈΠ΅Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 99

Автор Майкл ДТонсон

 38:  ptr = argv + 1;

 39:  while (*ptr && *ptr[0] == '-') {

 40:   if (!strcmp(*ptr, "β€”numerichost")) {

 41:    flags |= NI_NUMERICHOST;

 42:   } else if (!strcmp (*ptr, "--numericserv")) {

 43:    flags |= NI_NUMERICSERV;

 44:   } else if (!strcmp (*ptr, "--namereqd")) {

 45:    flags |= NI_NAMEREQD;

 46:   } else if (!strcmp(*ptr, "--nofqdn")) {

 47:    flags |= NI_NOFQDN;

 48:   } else if (!strcmp (*ptr, "--udp")) {

 49:    flags |= NI_DGRAM;

 50:   } else if (!strcmp(*ptr, "--host")) {

 51:    ptr++;

 52:    if (!*ptr) usage();

 53:    hostAddress = *ptr;

 54:   } else if (!strcmp(*ptr, "--service")) {

 55:    ptr++;

 56:    if (!*ptr) usage();

 57:    serviceAddress = *ptr;

 58:   } else

 59:    usage();

 60:

 61:   ptr++;

 62:  }

 63:

 64:  /* Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ адрСса hostAddress, serviceAddress ΠΈΠ»ΠΈ ΠΎΠ±Π° */

 65:  if (!hostAddress && !serviceAddress)

 66:   usage();

 67:

 68:  if (serviceAddress) {

 69:   char * end;

 70:

 71:   portNum = htons(strtol(serviceAddress, &end, 0));

 72:   if (*end) {

 73:    fprintf(stderr, "сбой ΠΏΡ€ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠΈ %s Π² число\n",

 74:     serviceAddress);

 75:    return 1;

 76:   }

 77:  }

 78:

 79:  if (!hostAddress) {

 80:   addr4.sin_family = AF_INET;

 81:   addr4.sin_port = portNum;

 82:  } else if (!strchr(hostAddress, ':')) {

 83:   /* Если hostAddress содСрТит Π΄Π²ΠΎΠ΅Ρ‚ΠΎΡ‡ΠΈΠ΅, Ρ‚ΠΎ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΠΌ Π²Π΅Ρ€ΡΠΈΡŽ IPv6.

 84:      Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС это IPv4 */

 85:

 86:   if (inet_pton(AF_INET, hostAddress,

 87:    &addr4.sin_addr) <= 0) {

 88:    fprintf(stderr, "ошибка прСобразования IPv4-адрСса %s\n",

 89:     hostAddress);

 90:    return 1;

 91:   }

 92:

 93:   addr4.sin_family = AF_INET;

 94:   addr4.sin_port = portNum;

 95:  } else {

 96:

 97:   memset(&addr6, 0, sizeof(addr6));

 98:

 99:   if (inet_pton(AF_INET6, hostAddress,

100:    &addr6.sin6_addr) <= 0) {

101:    fprintf(stderr, "ошибка прСобразования IPv6-адрСса %s\n",

102:     hostAddress);

103:    return 1;

104:   }

105:

106:   addr6.sin6_family = AF_INET6;

107:   addr6.sin6_port = portNum;

108:   addr = (struct sockaddr *) &addr6;

109:   addrLen = sizeof(addr6);

110:  }

111:

112:  if (!serviceAddress) {

113:   rc = getnameinfo(addr, addrLen, hostName, sizeof(hostName),

114:    NULL, 0, flags);

115:  } else if (!hostAddress) {

116:   rc = getnameinfo(addr, addrLen, NULL, 0,

117:    serviceName, sizeof(serviceName), flags);

118:  } else {

119:   rc = getnameinfo(addr, addrLen, hostName, sizeof(hostName),

120:    serviceName, sizeof(serviceName), flags);

121:  }

122:

123:  if (rc) {

124:   fprintf(stderr, "сбой ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ поиска: %s\n",

125:    gai_strerror(rc));

126:   return 1;

127:  }

128:

129:  if (hostAddress)

130:   printf("имя хоста: %s\n", hostName);

131:  if (serviceAddress)

132:   printf("имя слуТбы: %s\n", serviceName);

133:

134:  return 0;

135: }

17.5.7. ОТиданиС TCP-соСдинСний

ОТиданиС соСдинСний TCP происходит ΠΏΠΎΡ‡Ρ‚ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½ΠΎ оТиданию соСдинСний Π΄ΠΎΠΌΠ΅Π½Π° Unix. ЕдинствСнныС различия Π·Π°ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ Π² сСмСйствах ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠ² ΠΈ адрСсов. НиТС ΠΏΠΎΠΊΠ°Π·Π°Π½ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° сСрвСра Π΄ΠΎΠΌΠ΅Π½Π° Unix, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‡Π΅Ρ€Π΅Π· сокСты TCP.

 1: /* tserver.с */

 2:

 3: /* ΠžΠΆΠΈΠ΄Π°Π΅Ρ‚ соСдинСниС Π½Π° ΠΏΠΎΡ€Ρ‚Π΅ 4321. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ соСдинСниС установлСно,

 4:    ΠΈΠ· сокСта Π² stdout ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π΄Π°Π½Π½Ρ‹Π΅ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° вторая

 5:    сторона Π½Π΅ Π·Π°ΠΊΡ€ΠΎΠ΅Ρ‚ соСдинСниС. Π—Π°Ρ‚Π΅ΠΌ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ соСдинСниС

 6:    с сокСтом. */

 7:

 8: #include <arpa/inet.h>

 9: #include <netdb.h>

10: #include <netinet/in.h>

11: #include <stdio.h>

12: #include <string.h>

13: #include <sys/socket.h>

14: #include <unistd.h>

15:

16: #include "sockutil.h" /* Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ слуТСбныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ */

17:

18: int main(void) {

19:  int sock, conn, i, rc;

20:  struct sockaddr address;

21:  size_t addrLength = sizeof(address);

22:  struct addrinfo hints, * addr;

23:

24:  memset(&hints, 0, sizeof(hints));

25:

26:  hints.ai_socktype = SOCK_STREAM;

27:  hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;

28:  if ((rc = getaddrinfo(NULL, "4321", &hints, &addr))) {

29:   fprintf(stderr, "сбой поиска ΠΈΠΌΠ΅Π½ΠΈ хоста: %s\n",

30:   gai_strerror(rc));

31:   return 1;

32:  }

33:

34:  if ((sock = socket(addr->ai_family, addr->ai_socktype,

35:   addr->ai_protocol)) < 0)

36:   die("socket");

37:

38:  /* ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ядру ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ адрСс сокСта. Π­Ρ‚ΠΎ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚

39:     Π½Π°ΠΌ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Π΄Π²Π° Ρ€Π°Π·Π° подряд, Π½Π΅ оТидая ΠΏΠΎΠΊΠ° истСчСт

40:     Π²Ρ€Π΅ΠΌΡ для ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ° (ip-адрСс, ΠΏΠΎΡ€Ρ‚). */

41:  i = 1;

42:  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));

43:

44:  if (bind(sock, addr->ai_addr, addr->ai_addrlen))

45:   die("bind");

46:

47:  freeaddrinfo(addr);

48:

49:  if (listen(sock, 5))

50:   die("listen");

51:

52:  while ((conn = accept(sock, (struct sockaddr *) &address,

53:   &addrLength)) >=0) {

54:   printf("----ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ…\n");

55:   copyData(conn, 1);

56:   printf("----Π³ΠΎΡ‚ΠΎΠ²ΠΎ\n");

57:   close(conn);

58:  }

59:

60:  if (conn < 0)

61:   die("accept");

62:

63:  close(sock);

64:  return 0;

65: }

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ IP-адрСс, привязанный ΠΊ сокСту, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠΎΡ€Ρ‚Π° 4321, Π½ΠΎ Π½Π΅ IP-адрСс. Π­Ρ‚ΠΎ прСдоставляСт ядру Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ нСобходимости Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌ IP-адрСсом.

Код Π² строках 41–42 Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ объяснСния.

41: i = 1;

42: setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));

Linux-рСализация TCP, ΠΊΠ°ΠΊ ΠΈ Π² ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… систСмах Unix, Π²Π²ΠΎΠ΄ΠΈΡ‚ ограничСния Π½Π° Ρ‚ΠΎ, насколько скоро ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΡ€Ρ‚Π΅ΠΆ (Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ хост, Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΡ€Ρ‚)[136]. Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠ΄ устанавливаСт ΠΎΠΏΡ†ΠΈΡŽ Π½Π° сокСт, которая ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΡ‚ это ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ ΠΈ позволяСт Π΄Π²Π°ΠΆΠ΄Ρ‹ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ сСрвСр Π·Π° ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. По сходной ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ сСрвСр-ΠΏΡ€ΠΈΠΌΠ΅Ρ€ сокСта Π΄ΠΎΠΌΠ΅Π½Π° Unix удаляСт любой ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Π°ΠΉΠ» сокСта, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ bind().

Ѐункция setsockopt() позволяСт ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ мноТСство ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΎΠΏΡ†ΠΈΠΉ для сокСта ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°:

#include <sys/socket.h>


int setsockopt(int sock, int level, int option,

 const void * valptr, int vallength);

ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ β€” это сокСт, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ опрСдСляСтся опция. Π’Ρ‚ΠΎΡ€ΠΎΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚, level, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΈΠΏ устанавливаСмой ΠΎΠΏΡ†ΠΈΠΈ. Π’ нашСм сСрвСрС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ SOL_SOCKET, Ρ‡Ρ‚ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° установку ΠΎΠΏΡ†ΠΈΠΈ ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½ΠΎΠ³ΠΎ сокСта. ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ option опрСдСляСт ΠΎΠΏΡ†ΠΈΡŽ, которая ΠΏΠΎΠ΄Π»Π΅ΠΆΠΈΡ‚ измСнСнию. Π£ΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π½ΠΎΠ²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΎΠΏΡ†ΠΈΠΈ пСрСдаСтся Ρ‡Π΅Ρ€Π΅Π· valptr, Π° Ρ€Π°Π·ΠΌΠ΅Ρ€ значСния, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ valptr, пСрСдаСтся ΠΊΠ°ΠΊ vallength. Для нашСго сСрвСра примСняСтся ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Ρ†Π΅Π»ΠΎΠ΅ число, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π²Π²ΠΎΠ΄ΠΈΡ‚ Π² дСйствиС ΠΎΠΏΡ†ΠΈΡŽ SO_REUSEADDR.

17.5.8. ΠšΠ»ΠΈΠ΅Π½Ρ‚ΡΠΊΠΈΠ΅ прилоТСния TCP

ΠšΠ»ΠΈΠ΅Π½Ρ‚Ρ‹ TCP ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°ΠΌ Π΄ΠΎΠΌΠ΅Π½Π° Unix. Как ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, сразу ΠΆΠ΅ послС создания сокСта, ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊ сСрвСру с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ connect(). ЕдинствСнноС Ρ€Π°Π·Π»ΠΈΡ‡ΠΈΠ΅ состоит Π² способС ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ адрСса Π² connect(). ВмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ имя Ρ„Π°ΠΉΠ»Π°, Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² TCP ΠΎΡ‚Ρ‹ΡΠΊΠΈΠ²Π°ΡŽΡ‚ имя хоста Ρ‡Π΅Ρ€Π΅Π· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ getaddrinfo(), которая прСдоставляСт ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ для connect().

НиТС приводится нСслоТный TCP-ΠΊΠ»ΠΈΠ΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ взаимодСйствуСт с сСрвСром, прСдставлСнным Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅. Он ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΠ΄ΠΈΠ½ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚: имя хоста, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ сСрвСр, ΠΈΠ»ΠΈ Π΅Π³ΠΎ IP-Π½ΠΎΠΌΠ΅Ρ€ (Π² дСсятичном прСдставлСнии с Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ Ρ‚ΠΎΡ‡ΠΊΠ°ΠΌΠΈ). Π’ΠΎ всСм ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π²Π΅Π΄Π΅Ρ‚ сСбя Ρ‚Π°ΠΊΠΆΠ΅ ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ сокСта Π΄ΠΎΠΌΠ΅Π½Π° Unix, ΠΏΠΎΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ Ρ€Π°Π½Π΅Π΅ Π² этой Π³Π»Π°Π²Π΅.

 1: /* tclient.с */

 2:

 3: /* ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒΡΡ ΠΊ сСрвСру, Ρ‡ΡŒΠ΅ имя хоста ΠΈΠ»ΠΈ IP-адрСс ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Ρ‹ Π² качСствС

 4: Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°, Π½Π° ΠΏΠΎΡ€Ρ‚Π΅ 4321. ПослС соСдинСния ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ всС содСрТимоС

 5: stdin Π² сокСт, Π·Π°Ρ‚Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ. */

 6:

 7: #include <arpa/inet.h>

 8: #include <netdb.h>

 9: #include <netinet/in.h>

10: #include <stdio.h>

11: #include <stdlib.h>

12: #include <string.h>

13: #include <sys/socket.h>

14: #include <unistd.h>

15:

16: #include "sockutil.h" /* Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ слуТСбныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ */