Created
October 24, 2018 21:09
-
-
Save filinvadim/cbdea1c46e6f30195a2cb03254b8c6ae to your computer and use it in GitHub Desktop.
epoll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func serve() { | |
ep, err := netpoll.EpollCreate(epollConfig()) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Create listener on port 4444. | |
ln, err := listen(4444) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer unix.Close(ln) | |
done := make(chan struct{}) | |
var received bytes.Buffer | |
// Add listener fd to epoll instance to know when there are new incoming | |
// connections. | |
ep.Add(ln, netpoll.EPOLLIN, func(evt netpoll.EpollEvent) { | |
if evt&_EPOLLCLOSED != 0 { | |
return | |
} | |
// Accept new incoming connection. | |
nfd, _, err := unix.Accept(ln) | |
if err != nil { | |
log.Fatalf("could not accept: %s", err) | |
} | |
// Socket must not block read() from it. | |
unix.SetNonblock(nfd, true) | |
// Add connection fd to epoll instance to get notifications about | |
// available data. | |
ep.Add( | |
nfd, | |
netpoll.EPOLLIN|netpoll.EPOLLET|netpoll.EPOLLHUP|netpoll.EPOLLRDHUP, | |
func(evt netpoll.EpollEvent, | |
) { | |
// If EPOLLRDHUP is supported, it will be triggered after conn | |
// close() or shutdown(). In older versions EPOLLHUP is triggered. | |
if evt&_EPOLLCLOSED != 0 { | |
return | |
} | |
var buf [128]byte | |
for { | |
n, err := unix.Read(nfd, buf[:]) | |
if err != nil { | |
break | |
} | |
if n <= 0 { | |
break | |
} | |
received.Write(buf[:n]) | |
} | |
bIo := bufio.NewReader(bytes.NewReader(received.Bytes())) | |
req, err := http.ReadRequest(bIo) | |
fmt.Println(req, err, "!!!!!!!!!") | |
received.Reset() | |
}) | |
}) | |
<- done | |
if err = ep.Close(); err != nil { | |
log.Fatal(err) | |
} | |
} | |
func listen(port int) (ln int, err error) { | |
fmt.Println("start server") | |
ln, err = unix.Socket(unix.AF_INET, unix.O_NONBLOCK|unix.SOCK_STREAM, 0) | |
if err != nil { | |
return | |
} | |
// Need for avoid receiving EADDRINUSE error. | |
// Closed listener could be in TIME_WAIT state some time. | |
unix.SetsockoptInt(ln, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) | |
addr := &unix.SockaddrInet4{ | |
Port: port, | |
Addr: [4]byte{0x7f, 0, 0, 1}, // 127.0.0.1 | |
} | |
if err = unix.Bind(ln, addr); err != nil { | |
return | |
} | |
err = unix.Listen(ln, 4) | |
return | |
} | |
func epollConfig() *netpoll.EpollConfig { | |
return &netpoll.EpollConfig{ | |
OnWaitError: func(err error) { | |
log.Fatal(err) | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment