// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package netimport ()// BUG(mikio): On JS and Windows, the File method of TCPConn and// TCPListener is not implemented.// TCPAddr represents the address of a TCP end point.typeTCPAddrstruct { IP IP Port int Zone string// IPv6 scoped addressing zone}// Network returns the address's network name, "tcp".func ( *TCPAddr) () string { return"tcp" }func ( *TCPAddr) () string {if == nil {return"<nil>" } := ipEmptyString(.IP)if .Zone != "" {returnJoinHostPort(+"%"+.Zone, itoa(.Port)) }returnJoinHostPort(, itoa(.Port))}func ( *TCPAddr) () bool {if == nil || .IP == nil {returntrue }return .IP.IsUnspecified()}func ( *TCPAddr) () Addr {if == nil {returnnil }return}// ResolveTCPAddr returns an address of TCP end point.//// The network must be a TCP network name.//// If the host in the address parameter is not a literal IP address or// the port is not a literal port number, ResolveTCPAddr resolves the// address to an address of TCP end point.// Otherwise, it parses the address as a pair of literal IP address// and port number.// The address parameter can use a host name, but this is not// recommended, because it will return at most one of the host name's// IP addresses.//// See func Dial for a description of the network and address// parameters.func (, string) (*TCPAddr, error) {switch {case"tcp", "tcp4", "tcp6":case"": // a hint wildcard for Go 1.0 undocumented behavior = "tcp"default:returnnil, UnknownNetworkError() } , := DefaultResolver.internetAddrList(context.Background(), , )if != nil {returnnil, }return .forResolve(, ).(*TCPAddr), nil}// TCPConn is an implementation of the Conn interface for TCP network// connections.typeTCPConnstruct {conn}// SyscallConn returns a raw network connection.// This implements the syscall.Conn interface.func ( *TCPConn) () (syscall.RawConn, error) {if !.ok() {returnnil, syscall.EINVAL }returnnewRawConn(.fd)}// ReadFrom implements the io.ReaderFrom ReadFrom method.func ( *TCPConn) ( io.Reader) (int64, error) {if !.ok() {return0, syscall.EINVAL } , := .readFrom()if != nil && != io.EOF { = &OpError{Op: "readfrom", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }return , }// CloseRead shuts down the reading side of the TCP connection.// Most callers should just use Close.func ( *TCPConn) () error {if !.ok() {returnsyscall.EINVAL }if := .fd.closeRead(); != nil {return &OpError{Op: "close", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }returnnil}// CloseWrite shuts down the writing side of the TCP connection.// Most callers should just use Close.func ( *TCPConn) () error {if !.ok() {returnsyscall.EINVAL }if := .fd.closeWrite(); != nil {return &OpError{Op: "close", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }returnnil}// SetLinger sets the behavior of Close on a connection which still// has data waiting to be sent or to be acknowledged.//// If sec < 0 (the default), the operating system finishes sending the// data in the background.//// If sec == 0, the operating system discards any unsent or// unacknowledged data.//// If sec > 0, the data is sent in the background as with sec < 0. On// some operating systems after sec seconds have elapsed any remaining// unsent data may be discarded.func ( *TCPConn) ( int) error {if !.ok() {returnsyscall.EINVAL }if := setLinger(.fd, ); != nil {return &OpError{Op: "set", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }returnnil}// SetKeepAlive sets whether the operating system should send// keep-alive messages on the connection.func ( *TCPConn) ( bool) error {if !.ok() {returnsyscall.EINVAL }if := setKeepAlive(.fd, ); != nil {return &OpError{Op: "set", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }returnnil}// SetKeepAlivePeriod sets period between keep-alives.func ( *TCPConn) ( time.Duration) error {if !.ok() {returnsyscall.EINVAL }if := setKeepAlivePeriod(.fd, ); != nil {return &OpError{Op: "set", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }returnnil}// SetNoDelay controls whether the operating system should delay// packet transmission in hopes of sending fewer packets (Nagle's// algorithm). The default is true (no delay), meaning that data is// sent as soon as possible after a Write.func ( *TCPConn) ( bool) error {if !.ok() {returnsyscall.EINVAL }if := setNoDelay(.fd, ); != nil {return &OpError{Op: "set", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: } }returnnil}func ( *netFD) *TCPConn { := &TCPConn{conn{}}setNoDelay(.fd, true)return}// DialTCP acts like Dial for TCP networks.//// The network must be a TCP network name; see func Dial for details.//// If laddr is nil, a local address is automatically chosen.// If the IP field of raddr is nil or an unspecified IP address, the// local system is assumed.func ( string, , *TCPAddr) (*TCPConn, error) {switch {case"tcp", "tcp4", "tcp6":default:returnnil, &OpError{Op: "dial", Net: , Source: .opAddr(), Addr: .opAddr(), Err: UnknownNetworkError()} }if == nil {returnnil, &OpError{Op: "dial", Net: , Source: .opAddr(), Addr: nil, Err: errMissingAddress} } := &sysDialer{network: , address: .String()} , := .dialTCP(context.Background(), , )if != nil {returnnil, &OpError{Op: "dial", Net: , Source: .opAddr(), Addr: .opAddr(), Err: } }return , nil}// TCPListener is a TCP network listener. Clients should typically// use variables of type Listener instead of assuming TCP.typeTCPListenerstruct { fd *netFD lc ListenConfig}// SyscallConn returns a raw network connection.// This implements the syscall.Conn interface.//// The returned RawConn only supports calling Control. Read and// Write return an error.func ( *TCPListener) () (syscall.RawConn, error) {if !.ok() {returnnil, syscall.EINVAL }returnnewRawListener(.fd)}// AcceptTCP accepts the next incoming call and returns the new// connection.func ( *TCPListener) () (*TCPConn, error) {if !.ok() {returnnil, syscall.EINVAL } , := .accept()if != nil {returnnil, &OpError{Op: "accept", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: } }return , nil}// Accept implements the Accept method in the Listener interface; it// waits for the next call and returns a generic Conn.func ( *TCPListener) () (Conn, error) {if !.ok() {returnnil, syscall.EINVAL } , := .accept()if != nil {returnnil, &OpError{Op: "accept", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: } }return , nil}// Close stops listening on the TCP address.// Already Accepted connections are not closed.func ( *TCPListener) () error {if !.ok() {returnsyscall.EINVAL }if := .close(); != nil {return &OpError{Op: "close", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: } }returnnil}// Addr returns the listener's network address, a *TCPAddr.// The Addr returned is shared by all invocations of Addr, so// do not modify it.func ( *TCPListener) () Addr { return .fd.laddr }// SetDeadline sets the deadline associated with the listener.// A zero time value disables the deadline.func ( *TCPListener) ( time.Time) error {if !.ok() {returnsyscall.EINVAL }if := .fd.pfd.SetDeadline(); != nil {return &OpError{Op: "set", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: } }returnnil}// File returns a copy of the underlying os.File.// It is the caller's responsibility to close f when finished.// Closing l does not affect f, and closing f does not affect l.//// The returned os.File's file descriptor is different from the// connection's. Attempting to change properties of the original// using this duplicate may or may not have the desired effect.func ( *TCPListener) () ( *os.File, error) {if !.ok() {returnnil, syscall.EINVAL } , = .file()if != nil {returnnil, &OpError{Op: "file", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: } }return}// ListenTCP acts like Listen for TCP networks.//// The network must be a TCP network name; see func Dial for details.//// If the IP field of laddr is nil or an unspecified IP address,// ListenTCP listens on all available unicast and anycast IP addresses// of the local system.// If the Port field of laddr is 0, a port number is automatically// chosen.func ( string, *TCPAddr) (*TCPListener, error) {switch {case"tcp", "tcp4", "tcp6":default:returnnil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: UnknownNetworkError()} }if == nil { = &TCPAddr{} } := &sysListener{network: , address: .String()} , := .listenTCP(context.Background(), )if != nil {returnnil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: } }return , nil}// roundDurationUp rounds d to the next multiple of to.func ( time.Duration, time.Duration) time.Duration {return ( + - 1) / }