Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5695
  • 博文数量: 6
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2019-09-05 14:25
文章分类

全部博文(6)

文章存档

2019年(6)

我的朋友

分类: LINUX

2019-09-09 09:10:34

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

点击(此处)折叠或打开

  1. 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))
       }
      }
     }
    }
阅读(408) | 评论(0) | 转发(0) |
0

上一篇:go:网络编程初探

下一篇:Navicat连接mysql

给主人留下些什么吧!~~