OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // +build darwin freebsd linux netbsd openbsd windows | 5 // +build darwin freebsd linux netbsd openbsd windows |
6 | 6 |
7 // TCP sockets | 7 // TCP sockets |
8 | 8 |
9 package net | 9 package net |
10 | 10 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 if !c.ok() { | 136 if !c.ok() { |
137 return syscall.EINVAL | 137 return syscall.EINVAL |
138 } | 138 } |
139 return setNoDelay(c.fd, noDelay) | 139 return setNoDelay(c.fd, noDelay) |
140 } | 140 } |
141 | 141 |
142 // DialTCP connects to the remote address raddr on the network net, | 142 // DialTCP connects to the remote address raddr on the network net, |
143 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used | 143 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used |
144 // as the local address for the connection. | 144 // as the local address for the connection. |
145 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { | 145 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) { |
| 146 switch net { |
| 147 case "tcp", "tcp4", "tcp6": |
| 148 default: |
| 149 return nil, UnknownNetworkError(net) |
| 150 } |
| 151 if raddr == nil { |
| 152 return nil, &OpError{"dial", net, nil, errMissingAddress} |
| 153 } |
146 return dialTCP(net, laddr, raddr, noDeadline) | 154 return dialTCP(net, laddr, raddr, noDeadline) |
147 } | 155 } |
148 | 156 |
149 func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
rror) { | 157 func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
rror) { |
150 if raddr == nil { | |
151 return nil, &OpError{"dial", net, nil, errMissingAddress} | |
152 } | |
153 | |
154 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline,
syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) | 158 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline,
syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) |
155 | 159 |
156 // TCP has a rarely used mechanism called a 'simultaneous connection' in | 160 // TCP has a rarely used mechanism called a 'simultaneous connection' in |
157 // which Dial("tcp", addr1, addr2) run on the machine at addr1 can | 161 // which Dial("tcp", addr1, addr2) run on the machine at addr1 can |
158 // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machin
e | 162 // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machin
e |
159 // at addr2, without either machine executing Listen. If laddr == nil, | 163 // at addr2, without either machine executing Listen. If laddr == nil, |
160 // it means we want the kernel to pick an appropriate originating local | 164 // it means we want the kernel to pick an appropriate originating local |
161 // address. Some Linux kernels cycle blindly through a fixed range of | 165 // address. Some Linux kernels cycle blindly through a fixed range of |
162 // local ports, regardless of destination port. If a kernel happens to | 166 // local ports, regardless of destination port. If a kernel happens to |
163 // pick local port 50001 as the source for a Dial("tcp", "", "localhost:
50001"), | 167 // pick local port 50001 as the source for a Dial("tcp", "", "localhost:
50001"), |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 return ok && e.Err == syscall.EADDRNOTAVAIL | 221 return ok && e.Err == syscall.EADDRNOTAVAIL |
218 } | 222 } |
219 | 223 |
220 // TCPListener is a TCP network listener. | 224 // TCPListener is a TCP network listener. |
221 // Clients should typically use variables of type Listener | 225 // Clients should typically use variables of type Listener |
222 // instead of assuming TCP. | 226 // instead of assuming TCP. |
223 type TCPListener struct { | 227 type TCPListener struct { |
224 fd *netFD | 228 fd *netFD |
225 } | 229 } |
226 | 230 |
227 // ListenTCP announces on the TCP address laddr and returns a TCP listener. | |
228 // Net must be "tcp", "tcp4", or "tcp6". | |
229 // If laddr has a port of 0, it means to listen on some available port. | |
230 // The caller can use l.Addr() to retrieve the chosen address. | |
231 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { | |
232 fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.
SOCK_STREAM, 0, "listen", sockaddrToTCP) | |
233 if err != nil { | |
234 return nil, err | |
235 } | |
236 err = syscall.Listen(fd.sysfd, listenerBacklog) | |
237 if err != nil { | |
238 closesocket(fd.sysfd) | |
239 return nil, &OpError{"listen", net, laddr, err} | |
240 } | |
241 l := new(TCPListener) | |
242 l.fd = fd | |
243 return l, nil | |
244 } | |
245 | |
246 // AcceptTCP accepts the next incoming call and returns the new connection | 231 // AcceptTCP accepts the next incoming call and returns the new connection |
247 // and the remote address. | 232 // and the remote address. |
248 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) { | 233 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) { |
249 if l == nil || l.fd == nil || l.fd.sysfd < 0 { | 234 if l == nil || l.fd == nil || l.fd.sysfd < 0 { |
250 return nil, syscall.EINVAL | 235 return nil, syscall.EINVAL |
251 } | 236 } |
252 fd, err := l.fd.accept(sockaddrToTCP) | 237 fd, err := l.fd.accept(sockaddrToTCP) |
253 if err != nil { | 238 if err != nil { |
254 return nil, err | 239 return nil, err |
255 } | 240 } |
(...skipping 28 matching lines...) Expand all Loading... |
284 if l == nil || l.fd == nil { | 269 if l == nil || l.fd == nil { |
285 return syscall.EINVAL | 270 return syscall.EINVAL |
286 } | 271 } |
287 return setDeadline(l.fd, t) | 272 return setDeadline(l.fd, t) |
288 } | 273 } |
289 | 274 |
290 // File returns a copy of the underlying os.File, set to blocking mode. | 275 // File returns a copy of the underlying os.File, set to blocking mode. |
291 // It is the caller's responsibility to close f when finished. | 276 // It is the caller's responsibility to close f when finished. |
292 // Closing l does not affect f, and closing f does not affect l. | 277 // Closing l does not affect f, and closing f does not affect l. |
293 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() } | 278 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() } |
| 279 |
| 280 // ListenTCP announces on the TCP address laddr and returns a TCP listener. |
| 281 // Net must be "tcp", "tcp4", or "tcp6". |
| 282 // If laddr has a port of 0, it means to listen on some available port. |
| 283 // The caller can use l.Addr() to retrieve the chosen address. |
| 284 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { |
| 285 switch net { |
| 286 case "tcp", "tcp4", "tcp6": |
| 287 default: |
| 288 return nil, UnknownNetworkError(net) |
| 289 } |
| 290 if laddr == nil { |
| 291 laddr = &TCPAddr{} |
| 292 } |
| 293 fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.
SOCK_STREAM, 0, "listen", sockaddrToTCP) |
| 294 if err != nil { |
| 295 return nil, err |
| 296 } |
| 297 err = syscall.Listen(fd.sysfd, listenerBacklog) |
| 298 if err != nil { |
| 299 closesocket(fd.sysfd) |
| 300 return nil, &OpError{"listen", net, laddr, err} |
| 301 } |
| 302 l := new(TCPListener) |
| 303 l.fd = fd |
| 304 return l, nil |
| 305 } |
OLD | NEW |