Подтвердить что ты не робот

Go: http-сервер не работает на osx

пример http-сервера не работает для меня. Исходный код:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe("127.0.0.1:8080", nil)
}

Когда я пытаюсь подключить все, что я получаю, это:

$ curl 127.0.0.1:8080
curl: (7) Failed to connect to 127.0.0.1 port 8080: Operation timed out
$ nc -v -G 5 127.0.0.1 8080
nc: connectx to 127.0.0.1 port 8080 (tcp) failed: Operation timed out

Пока nc пытается подключиться, tcpdump показывает только SYN-пакеты:

$ tcpdump -i lo0 port 8080
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
18:21:30.906638 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118569352 ecr 0,sackOK,eol], length 0
18:21:31.006824 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118569452 ecr 0,sackOK,eol], length 0
18:21:31.106989 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118569552 ecr 0,sackOK,eol], length 0
18:21:31.208141 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118569653 ecr 0,sackOK,eol], length 0
18:21:31.308288 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118569753 ecr 0,sackOK,eol], length 0
18:21:31.408336 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118569853 ecr 0,sackOK,eol], length 0
18:21:31.609143 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118570053 ecr 0,sackOK,eol], length 0
18:21:32.011215 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118570453 ecr 0,sackOK,eol], length 0
18:21:32.812512 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118571253 ecr 0,sackOK,eol], length 0
18:21:34.414686 IP localhost.52799 > localhost.http-alt: Flags [S], seq 3375761924, win 65535, options [mss 16344,nop,wscale 5,nop,nop,TS val 118572853 ecr 0,sackOK,eol], length 0

И вот последняя часть вывода dtruss на стороне сервера (начиная с вызова сокета):

socket(0x2, 0x1, 0x0)            = 3 0
fcntl(0x3, 0x2, 0x1)             = 0 0
fcntl(0x3, 0x3, 0x0)             = 2 0
fcntl(0x3, 0x4, 0x6)             = 0 0
setsockopt(0x3, 0xFFFF, 0x20)            = 0 0
setsockopt(0x3, 0xFFFF, 0x4)             = 0 0
bind(0x3, 0xC8200BA6AC, 0x10)            = 0 0
listen(0x3, 0xFDE8, 0x10)                = 0 0
kqueue(0x3, 0xFDE8, 0x10)                = 4 0
fcntl(0x4, 0x2, 0x1)             = 0 0
kevent(0x4, 0xC8200558C0, 0x2)           = 0 0
getsockname(0x3, 0xC82005592C, 0xC820055928)             = 0 0
accept(0x3, 0xC820055AA4, 0xC820055A94)          = -1 Err#35
kevent(0x4, 0x0, 0x0)            = 0 0
select(0x0, 0x0, 0x0, 0x0, 0x700000080DE8)               = 0 0

При запуске nc ничего больше не появляется, поэтому он даже не замечает попыток подключения.

У меня нет брандмауэра, все работает, только программы Go имеют эту проблему (в частности, я не могу использовать докер-машину)

Как это исправить?

Изменить: Я предполагаю, что # Err35:

#define EDEADLK     35  /* Resource deadlock would occur */

... ваты?

Edit2:

  • go: версия go1.6 darwin/amd64
  • OSX: 10.11.4

Сервер не выходит, он слушает бесконечно.

Edit3:

Я попробовал как "go build", так и "go run - без разницы"

Использование localhost вместо 127.0.0.1 - без разницы

Использование w.Write([]byte(fmt.Sprintf("Hi there, I love %s!", r.URL.Path[1:])) вместо этого - никакой разницы. Btw - он говорит nc: connectx to 127.0.0.1 port 8080 (tcp) failed: Operation timed out, поэтому попытка подключения отключается, а не читать

ifconfig -a и netstat -r вывод: https://gist.github.com/mabn/ed171f180725b563d32bb86d5ec61988

4b9b3361

Ответ 1

Я исправил это! Я помнил, что раньше я пытался увеличить лимит подключений на своей машине и применял описанные здесь изменения: https://apple.stackexchange.com/a/169606

Вернувшись, исправлена ​​проблема. Это помогло:

sudo rm /etc/sysctl.conf
sudo sysctl kern.ipc.somaxconn=128
sudo rm /Library/LaunchDaemons/limit.maxproc.plist
sudo rm /Library/LaunchDaemons/limit.maxfiles.plist

Btw: после еще нескольких исследований я узнал, что:

  • проблема заключалась в том, что accept() syscall возвращал EAGAIN каждый раз, но не принимал никаких соединений
  • он вел себя одинаково для неблокирующих соединений в программах на C и Java

Но я до сих пор не знаю, почему именно он был сломан.

Ответ 2

Я хотел бы видеть вывод 'ifconfig -a'.

Это пахнет проблемой локальной конфигурации; Я не могу воспроизвести это на OS X 10.11.4, Go 1.6

My W.A.G - это то, что туннельное устройство фактически использует 127.0.0.1, а не устройство обратной связи.

Ответ 3

Установлен ли Cisco Anyconnect? Если так, найдите websecurity_uninstall.sh и удалите websecurity

sudo /opt/cisco/anyconnect/bin/websecurity_uninstall.sh

Он пересылает порт 8080 в порт 5001, и вы не можете использовать netstat, lsof или любой из обычных инструментов, чтобы понять, почему ничто не может использовать порт 8080.