Я знаком с сокетами Unix для межпроцессного взаимодействия и следую руководству здесь. Каждый раз, когда я запускаю программу, которая действует как сервер (в руководстве она называется echos.c), я получаю сообщение об ошибке bind: Address already in use
, за исключением первого запуска после удаления всех файлов сборки.
Ошибка исходит из этого раздела кода:
#define SOCK_PATH "echo_socket"
int main(void)
{
int s, s2, len;
socklen_t t;
struct sockaddr_un local, remote;
char str[100];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
// ...
При первоначальном запуске программа создает файл сокета с именем echo_socke
(я проверил это с помощью ls -l
, и странно, что в имени отсутствует буква 't', чтобы получилось echo_socket
), а затем успешно переходит к bind
и listen
для клиентский процесс.
Однако при последующих запусках, когда я не удаляю файлы сборки, я получаю ошибку bind: Address already in use
, исходящую из строк
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
Выполняя дополнительное тестирование, я обнаружил, что unlink(local.sun_path)
возвращает ошибку No such file or directory
, поэтому я полагаю, что файл сокета, к которому bind
пытается получить доступ, не найден. Может ли это быть из-за того, что в имени файла отсутствует символ, как упоминалось ранее? (Но это срабатывает с первого раза, так что не может быть?). Любая помощь в выяснении того, что происходит, будет очень признательна.
len
. См. man 7 unix. Это должно бытьoffsetof(struct sockaddr_un, sun_path)+strlen(local.sun_path)+1
. - person user207421   schedule 28.10.2019bind()
ожидает, что длина будет содержать конечный ноль, как вы можете видеть из формулы. Таким образом, он предположил, что последний символ был завершающим нулем, и усек имя. Итак, вашunlink()
не отключил его, значит, он все еще был там, так что «адрес уже используется». Конечно, при подключении нужно использовать ту же формулу. - person user207421   schedule 28.10.2019offsetof(struct sockaddr_un, sun_path)+strlen(local.sun_path)
байтов структуры. Паршивый дизайн. Они не должны были требовать +1. Слишком поздно. - person user207421   schedule 28.10.2019