Сокеты: TCP и UDP соединения (C язык) - PullRequest
0 голосов
/ 12 января 2020

У меня есть процесс, который должен установить sh сервер, который принимает TCP-соединения и создать несколько дочерних процессов для выполнения этой работы. Я создаю сокет TCP (без прослушивания, связывания или принятия) и затем с разветвлением. У меня есть следующие вопросы:

  1. Если я свяжу этот сокет с портом и прослушу этот порт, также будет ли сокет, который был разветвлен перед этими двумя вызовами, прослушать и привязать к тот самый порт?

  2. Если я использую accept на сокете, и сокет принимает соединение и связывается с клиентским сокетом: будут ли также соединены розетки, которые были разветвлены, с этим клиентским сокетом?

Я знаю, что таблица fd совместно используется отцом и детьми, но я не знаю, будут ли какие-либо изменения, которые происходят с сокетом в процессе отца, также произойдут с детьми.

Могу ли я использовать сокет, открытый для соединений TCP, в качестве получателя TCP и отправителя UDP?

Можно ли использовать сокет, открытый для соединений TCP, в качестве приемника UDP и отправителя TCP?

Если у меня есть сокет, который был открыт для соединений TCP: Могу ли я без проблем использовать sendto с последними 2 аргументами NULL? В онлайн-руководстве я обнаружил, что для сокетов на основе соединений можно пропустить последние 2 аргумента, но я не знаю, правильно ли я их понимаю. Если это возможно, я хочу, чтобы дети могли отправлять ответы дейтаграммы клиенту, ожидающему с recvfrom, не зная его адреса.

Можно ли использовать на клиентском сокете, к которому был подключен TCP, recvfrom с последними 2 аргументами NULL?

1 Ответ

2 голосов
/ 13 января 2020

1. Если я свяжу этот сокет с портом и прослушу этот порт, будет ли также сокет, который был разветвлен перед этими двумя вызовами, прослушать и привязать к тому же порту?

Как только вы иметь дескриптор файла (созданный с помощью socket или accept), изменения этого дескриптора файла отражаются в клонах этого дескриптора во всех процессах.

Поскольку вы не можете связать сокет дважды, Следующее может быть использовано для подтверждения моей претензии. (Он написан на Perl, но C программист должен иметь возможность прочитать его без проблем. die выдает исключение, $! равно strerror(errno), а $!{EINVAL} эквивалентно errno == EINVAL.)

#!/usr/bin/perl

use 5.014;
use warnings;

use Socket qw( pack_sockaddr_in AF_INET SOCK_STREAM INADDR_ANY SOMAXCONN );

socket(my $socket, AF_INET, SOCK_STREAM, 0)
   or die("socket: $!\n");

defined( my $pid = fork() )
   or die("fork: $!\n");

if (!$pid) {
   bind($socket, pack_sockaddr_in(0, INADDR_ANY))
      or die("bind: $!\n");
   listen($socket, SOMAXCONN)
      or die("listen: $!\n");
   exit;
}

waitpid($pid, 0) > 0
   or die("waitpid: $!\n");

if (bind($socket, pack_sockaddr_in(0, INADDR_ANY))) {
   say "Socket bound again. bind doesn't transcend processes.";
} else {
   if ($!{EINVAL}) {
      say "Socket already bound. bind transcends processes.";
   } else {
      die("bind in parent: $!\n");
   }
}

Вывод:

Socket already bound. bind transcends processes.

2. Если я использую accept на сокете, и сокет принимает соединение и связывается с клиентским сокетом: Будут ли также сокеты, которые были разветвлены, соединены с этим клиентским сокетом?

Нет. Этот вопрос предполагает существование связи / соединения между сокетом, созданным accept, и сокетом, в котором был вызван accept, но такой связи / соединения нет (ни в одном из процессов).


3. Могу ли я использовать сокет, открытый для соединений TCP, в качестве получателя TCP и отправителя UDP?

4. Могу ли я использовать сокет, открытый для соединений TCP, в качестве приемника UDP и отправителя TCP?

Нет. Сокет - это либо сокет TCP, либо сокет UDP. Вы не можете отправлять / получать пакеты UDP через сокет TCP, и вы не можете отправлять / получать пакеты TCP через сокет UDP. Невозможно даже попробовать.

Однако порты TCP и UDP независимы, поэтому вы можете использовать TCP-порт 1234 и UDP-порт 1234 одновременно (используя два разных сокета).


5. Если у меня есть сокет, который был открыт для соединений TCP: Могу ли я использовать sendto с последними 2 аргументами NULL без проблем?

Да. send может быть вызвано для сокетов TCP, а send определяется в терминах sendto с NULL и 0 для последних двух аргументов.

Согласно man 2 send на моем (GNU / Linux) system:

send(sockfd, buf, len, flags); эквивалентно sendto(sockfd, buf, len, flags, NULL, 0);

Фактически, вы должны установить два последних аргумента в NULL и 0 с сокетом TCP.

В соответствии с man 2 sendto в моей (GNU / Linux) системе:

Если sendto() используется для соединения- В режиме (SOCK_STREAM, SOCK_SEQPACKET) сокета аргументы dest_addr и addrlen игнорируются (и ошибка EISCONN может быть возвращена, если они не NULL и 0)


6. Могу ли я использовать на клиентском сокете, к которому был подключен TCP, recvfrom с последними 2 аргументами NULL?

Да. recv можно вызывать для сокетов TCP, а recv определяется в терминах recvfrom с NULL для последних двух аргументов.

Согласно man 2 recv на моем (GNU / Linux) система:

recv(sockfd, buf, len, flags); эквивалентна recvfrom(sockfd, buf, len, flags, NULL, NULL);

...