Вы дважды закрываете сокет.
let (s, _caller) = Unix.accept socket_desc
Теперь у вас есть дескриптор файла Unix s
вашего сокета.
let inchan = Unix.in_channel_of_descr s
and outchan = Unix.out_channel_of_descr s
Теперь у вас есть входные и выходные каналы OCaml ссокет как их основные потоки.
Unix.close s;
Теперь вы закрыли конечные точки чтения / записи сокета Unix.
close_out outchan;
Теперь вы пытаетесь закрыть сокет во второй раз.Поскольку базовый поток уже закрыт, это ошибка.
Способ посмотреть на это (ИМХО) заключается в следующем:
let inchan = Unix.in_channel_of_descr s
and outchan = Unix.out_channel_of_descr s
Вы подписываете договор, а неиспользовать базовый сокет Unix больше.С этого момента вы должны иметь дело только с каналами OCaml.
Если вы удалите Unix.close s
, все должно работать (или не работать при следующей проблеме: -)
Обновление
Я запустил указанный вами код из учебника, и он также получает исключение плохого дескриптора файла.
Возможно, это ошибочный учебник.
Похоже, что и close_in
, и close_out
собираются полностью закрыть сокет (и, следовательно, не оставлять его в так называемом полуоткрытом состоянии).Поэтому я бы просто позвонил close_out
.
. Может быть, лучше сделать ввод-вывод через сокет полностью через интерфейс Unix.Кажется немного хрупким, когда два канала OCaml используют один и тот же дескриптор файла.
Обновление 2
Вы можете использовать Unix.dup
, чтобы получить второй дескриптор файла для использованиядля одного из двух каналов OCaml.Полученный код кажется мне гораздо менее хрупким:
match Unix.fork() with
| 0 ->
(* Child process *)
if Unix.fork() <> 0 then exit 0; (* Daemonize *)
print_string "Got a connection!";
flush stdout;
let s' = Unix.dup s in
let inchan = Unix.in_channel_of_descr s
and outchan = Unix.out_channel_of_descr s' in
output_string outchan "Hello world!";
flush outchan;
close_in inchan;
close_out outchan;
exit 0
| id ->
(* Parent process *)
Unix.close s;
ignore(Unix.waitpid [] id)
Я протестировал этот код, и он работал без исключений из-за плохих дескрипторов файлов.