IP-адрес в TCP-сокетах - PullRequest
       24

IP-адрес в TCP-сокетах

1 голос
/ 08 июля 2011

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

Таким образом, у меня должен быть IP-адрес каждого узла, подключенного к серверу.Как я могу получить эту информацию?

Ответы [ 3 ]

2 голосов
/ 08 июля 2011

Это более нюансированный вопрос, чем кажется на первый взгляд.

Если клиенты сидят за NAT, вы можете получить один и тот же IP от нескольких клиентов.Это совершенно естественное и ожидаемое поведение.Если вам необходимо различать несколько клиентов за одним и тем же NAT, вам понадобится другая форма уникального идентификатора клиента (например, IP-адрес и порт).

2 голосов
/ 08 июля 2011

Когда вы звоните accept(2), вы можете выбрать получение адреса клиента.

int accept(int socket, struct sockaddr *restrict address,
    socklen_t *restrict address_len);

Вам нужно сохранить эти адреса, а затем send(2) для каждого, что вам нужно отправить.

Так что рабочий процесс должен быть примерно таким:

  • Вести список подключенных клиентов. Изначально список пуст, конечно
  • Когда вы принимаете соединение, вставьте его данные в этот список (адрес и сокет, возвращаемый accept(2)).
  • Когда вам нужно отправить что-то каждому клиенту, просто просмотрите список и отправьте его (используя сохраненный сокет)

Единственная сложность заключается в том, что socklen_t *restrict address_len является аргументом значение-результат, поэтому с этим нужно быть осторожным.

1 голос
/ 08 июля 2011

Пока у вас есть доступ к списку файловых дескрипторов для подключенных TCP-сокетов, можно легко получить адреса удаленных хостов.Ключом является системный вызов getpeername(), который позволяет узнать адрес удаленного конца сокета.Образец кода C:

// This is ugly, but simpler than the alternative
union {
    struct sockaddr sa;
    struct sockaddr_in sa4;
    struct sockaddr_storage sas;
} address;
socklen_t size = sizeof(address);

// Assume the file descriptor is in the var 'fd':
if (getpeername(fd, &address.sa, &size) < 0) {
    // Deal with error here...
}

if (address.sa.family == AF_INET) {
    // IP address now in address.sa4.sin_addr, port in address.sa4.sin_port
} else {
    // Some other kind of socket...
}
...