Skip to content

Instantly share code, notes, and snippets.

@wathenjiang
Last active December 31, 2021 02:56
Show Gist options
  • Save wathenjiang/f2bccc06ccf7852dc9b57e0d97af82a0 to your computer and use it in GitHub Desktop.
Save wathenjiang/f2bccc06ccf7852dc9b57e0d97af82a0 to your computer and use it in GitHub Desktop.
gnet_client_nodelay_test
// Dial is like net.Dial().
func (cli *Client) Dial(network, address string) (Conn, error) {
c, err := net.Dial(network, address)
if err != nil {
return nil, err
}
defer c.Close()
sc, ok := c.(syscall.Conn)
if !ok {
return nil, errors.New("failed to convert net.Conn to syscall.Conn")
}
rc, err := sc.SyscallConn()
if err != nil {
return nil, errors.New("failed to get syscall.RawConn from net.Conn")
}
var DupFD int
e := rc.Control(func(fd uintptr) {
DupFD, err = unix.Dup(int(fd)) // 利用闭包修改了 err
})
if err != nil {
return nil, err
}
if e != nil {
return nil, e
}
if strings.HasPrefix(network, "tcp") {
value, err := unix.GetsockoptUint64(DupFD, unix.IPPROTO_TCP, unix.TCP_NODELAY)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
fmt.Println("before set value: ", value)
if cli.opts.TCPNoDelay == TCPDelay {
if err = socket.SetNoDelay(DupFD, 0); err != nil {
return nil, err
}
}
value, err = unix.GetsockoptUint64(DupFD, unix.IPPROTO_TCP, unix.TCP_NODELAY)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
fmt.Println("after set value: ", value)
if cli.opts.TCPKeepAlive > 0 {
if err = socket.SetKeepAlive(DupFD, int(cli.opts.TCPKeepAlive/time.Second)); err != nil {
return nil, err
}
}
}
if cli.opts.SocketSendBuffer > 0 {
if err = socket.SetSendBuffer(DupFD, cli.opts.SocketSendBuffer); err != nil {
return nil, err
}
}
if cli.opts.SocketRecvBuffer > 0 {
if err = socket.SetRecvBuffer(DupFD, cli.opts.SocketRecvBuffer); err != nil {
return nil, err
}
}
var (
sockAddr unix.Sockaddr
gc Conn
)
switch c.(type) {
case *net.UnixConn:
if sockAddr, _, _, err = socket.GetUnixSockAddr(c.RemoteAddr().Network(), c.RemoteAddr().String()); err != nil {
return nil, err
}
ua := c.LocalAddr().(*net.UnixAddr)
ua.Name = c.RemoteAddr().String() + "." + strconv.Itoa(DupFD)
gc = newTCPConn(DupFD, cli.el, sockAddr, cli.opts.Codec, c.LocalAddr(), c.RemoteAddr())
case *net.TCPConn:
if sockAddr, _, _, _, err = socket.GetTCPSockAddr(c.RemoteAddr().Network(), c.RemoteAddr().String()); err != nil {
return nil, err
}
gc = newTCPConn(DupFD, cli.el, sockAddr, cli.opts.Codec, c.LocalAddr(), c.RemoteAddr())
case *net.UDPConn:
if sockAddr, _, _, _, err = socket.GetUDPSockAddr(c.RemoteAddr().Network(), c.RemoteAddr().String()); err != nil {
return nil, err
}
gc = newUDPConn(DupFD, cli.el, c.LocalAddr(), sockAddr, true)
default:
return nil, gerrors.ErrUnsupportedProtocol
}
err = cli.el.poller.UrgentTrigger(cli.el.register, gc)
if err != nil {
gc.Close()
return nil, err
}
return gc, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment