ITPub博客

首页 > 应用开发 > > go语言网络编程--epoll

go语言网络编程--epoll

作者:zzzhangyi 时间:2019-09-12 15:17:27 0 删除 编辑

如下为go使用epoll的例子,采用 syscall.Socket、syscall.SetNonblock、syscall.Bind、syscall.Listen系统调用来监听端口,然后采用syscall.EpollCreate1、syscall.EpollCtl、syscall.EpollWait来关联这个监听的文件描述符, 一旦有新的连接的事件过来,使用syscall.Accept接收连接请求,并对这个连接文件描述符调用syscall.EpollCtl监听数据事件。一旦连接有数据就绪, 则调用syscall.Read读数据,有必要则调用syscall.Write写数据。

package main
import (
 "fmt"
 "net"
 "os"
 "syscall"
)
const (
 EPOLLET = 1 << 31
 MaxEpollEvents = 32
)
func echo(fd int) {
 defer syscall.Close(fd)
 var buf [32 * 1024]byte
 for {
 nbytes, e := syscall.Read(fd, buf[:])
 if nbytes > 0 {
 fmt.Printf(">>> %s", buf)
 syscall.Write(fd, buf[:nbytes])
 fmt.Printf("<<< %s", buf)
 }
 if e != nil {
 break
  }
 }
}
func main() {
  var event syscall.EpollEvent
  var events [MaxEpollEvents]syscall.EpollEvent
  fd, err := syscall.Socket(syscall.AF_INET, syscall.O_NONBLOCK|syscall.SOCK_STREAM, 0)//创建socket
  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: 50000}   
  copy(addr.Addr[:], net.ParseIP("0.0.0.0").To4())
  syscall.Bind(fd, &addr)   //绑定ip,端口。
  syscall.Listen(fd, 10)  //监听端口
  epfd, e := syscall.EpollCreate1(0)  
  if e != nil {
    fmt.Println("epoll_create1: ", e)
    os.Exit(1)
  }
  defer syscall.Close(epfd)
  event.Events = syscall.EPOLLIN
  event.Fd = int32(fd) //设置监听描述符
  if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil {
    fmt.Println("epoll_ctl: ", e)
    os.Exit(1)
  }
  for {
    nevents, e := syscall.EpollWait(epfd, events[:], -1)  //获取就绪事件
    if e != nil {
      fmt.Println("epoll_wait: ", e)
      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))
   }
  }
 }
}


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/3598/viewspace-3118191/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-14

  • 博文量
    133
  • 访问量
    947