Skip to content

Instantly share code, notes, and snippets.

@filinvadim
Created October 24, 2018 21:48
Show Gist options
  • Save filinvadim/ebfe9487fd80e36ce738d0d1e16bfffa to your computer and use it in GitHub Desktop.
Save filinvadim/ebfe9487fd80e36ce738d0d1e16bfffa to your computer and use it in GitHub Desktop.
epoll2
package main
import (
"fmt"
"net"
"os"
"syscall"
)
const (
EPOLLET = 1 << 31
MaxEpollEvents = 32
)
func serve(host string, port int) {
var event syscall.EpollEvent
var events [MaxEpollEvents]syscall.EpollEvent
var err error
var fd int
fd, err = syscall.Socket(syscall.AF_INET, syscall.O_NONBLOCK|syscall.SOCK_STREAM, 0)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer syscall.Close(fd)
if err = syscall.SetNonblock(fd, true); err != nil {
fmt.Println("setnonblock1: ", err)
os.Exit(1)
}
addr := syscall.SockaddrInet4{Port: port} //4444
copy(addr.Addr[:], net.ParseIP(host).To4()) //"0.0.0.0"
if err = syscall.Bind(fd, &addr); err != nil {
fmt.Println("bind: ", err)
os.Exit(1)
}
if err = syscall.Listen(fd, 10); err != nil {
fmt.Println("listen: ", err)
os.Exit(1)
}
epfd, err := syscall.EpollCreate1(0)
if err != nil {
fmt.Println("epoll_create1: ", err)
os.Exit(1)
}
defer syscall.Close(epfd)
event.Events = syscall.EPOLLIN
event.Fd = int32(fd)
if err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); err != nil {
fmt.Println("epoll_ctl: ", err)
os.Exit(1)
}
for {
nevents, err := syscall.EpollWait(epfd, events[:], -1)
if err != nil {
fmt.Println("epoll_wait: ", err)
break
}
for ev := 0; ev < nevents; ev++ {
if int(events[ev].Fd) == fd {
connFd, _, err := syscall.Accept(fd)
if err != nil {
fmt.Println("accept: ", err)
continue
}
syscall.SetNonblock(fd, true)
event.Events = syscall.EPOLLIN | EPOLLET
event.Fd = int32(connFd)
if err := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, connFd, &event); err != nil {
fmt.Print("epoll_ctl: ", connFd, err)
os.Exit(1)
}
} else {
go echo(int(events[ev].Fd))
}
}
}
}
func echo(fd int) {
defer syscall.Close(fd)
var buf [32 * 1024]byte
for {
nbytes, err := syscall.Read(fd, buf[:])
if nbytes > 0 {
fmt.Printf(">>> %s", buf)
syscall.Write(fd, buf[:nbytes])
fmt.Printf("<<< %s", buf)
}
if err != nil {
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment