LEFT | RIGHT |
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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 // (Nagle's algorithm). The default is true (no delay), meaning | 133 // (Nagle's algorithm). The default is true (no delay), meaning |
134 // that data is sent as soon as possible after a Write. | 134 // that data is sent as soon as possible after a Write. |
135 func (c *TCPConn) SetNoDelay(noDelay bool) error { | 135 func (c *TCPConn) SetNoDelay(noDelay bool) error { |
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 | 143 // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used |
144 // used 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 { | 146 switch net { |
147 case "tcp", "tcp4", "tcp6": | 147 case "tcp", "tcp4", "tcp6": |
148 default: | 148 default: |
149 return nil, UnknownNetworkError(net) | 149 return nil, UnknownNetworkError(net) |
150 } | 150 } |
151 if raddr == nil { | 151 if raddr == nil { |
152 return nil, &OpError{"dial", net, nil, errMissingAddress} | 152 return nil, &OpError{"dial", net, nil, errMissingAddress} |
153 } | 153 } |
154 | 154 » return dialTCP(net, laddr, raddr, noDeadline) |
155 » fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.S
OCK_STREAM, 0, "dial", sockaddrToTCP) | 155 } |
| 156 |
| 157 func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
rror) { |
| 158 » fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline,
syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) |
156 | 159 |
157 // TCP has a rarely used mechanism called a 'simultaneous connection' in | 160 // TCP has a rarely used mechanism called a 'simultaneous connection' in |
158 // 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 |
159 // 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 |
160 // at addr2, without either machine executing Listen. If laddr == nil, | 163 // at addr2, without either machine executing Listen. If laddr == nil, |
161 // 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 |
162 // address. Some Linux kernels cycle blindly through a fixed range of | 165 // address. Some Linux kernels cycle blindly through a fixed range of |
163 // local ports, regardless of destination port. If a kernel happens to | 166 // local ports, regardless of destination port. If a kernel happens to |
164 // 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"), |
165 // then the Dial will succeed, having simultaneously connected to itself
. | 168 // then the Dial will succeed, having simultaneously connected to itself
. |
166 // This can only happen when we are letting the kernel pick a port (ladd
r == nil) | 169 // This can only happen when we are letting the kernel pick a port (ladd
r == nil) |
167 // and when there is no listener for the destination address. | 170 // and when there is no listener for the destination address. |
168 // It's hard to argue this is anything other than a kernel bug. If we | 171 // It's hard to argue this is anything other than a kernel bug. If we |
169 // see this happen, rather than expose the buggy effect to users, we | 172 // see this happen, rather than expose the buggy effect to users, we |
170 // close the fd and try again. If it happens twice more, we relent and | 173 // close the fd and try again. If it happens twice more, we relent and |
171 // use the result. See also: | 174 // use the result. See also: |
172 // http://golang.org/issue/2690 | 175 // http://golang.org/issue/2690 |
173 // http://stackoverflow.com/questions/4949858/ | 176 // http://stackoverflow.com/questions/4949858/ |
174 // | 177 // |
175 // The opposite can also happen: if we ask the kernel to pick an appropr
iate | 178 // The opposite can also happen: if we ask the kernel to pick an appropr
iate |
176 // originating local address, sometimes it picks one that is already in
use. | 179 // originating local address, sometimes it picks one that is already in
use. |
177 // So if the error is EADDRNOTAVAIL, we have to try again too, just for | 180 // So if the error is EADDRNOTAVAIL, we have to try again too, just for |
178 // a different reason. | 181 // a different reason. |
179 // | 182 // |
180 // The kernel socket code is no doubt enjoying watching us squirm. | 183 // The kernel socket code is no doubt enjoying watching us squirm. |
181 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(f
d, err) || spuriousENOTAVAIL(err)); i++ { | 184 for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(f
d, err) || spuriousENOTAVAIL(err)); i++ { |
182 if err == nil { | 185 if err == nil { |
183 fd.Close() | 186 fd.Close() |
184 } | 187 } |
185 » » fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), sy
scall.SOCK_STREAM, 0, "dial", sockaddrToTCP) | 188 » » fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), de
adline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP) |
186 } | 189 } |
187 | 190 |
188 if err != nil { | 191 if err != nil { |
189 return nil, err | 192 return nil, err |
190 } | 193 } |
191 return newTCPConn(fd), nil | 194 return newTCPConn(fd), nil |
192 } | 195 } |
193 | 196 |
194 func selfConnect(fd *netFD, err error) bool { | 197 func selfConnect(fd *netFD, err error) bool { |
195 // If the connect failed, we clearly didn't connect to ourselves. | 198 // If the connect failed, we clearly didn't connect to ourselves. |
(...skipping 22 matching lines...) Expand all Loading... |
218 return ok && e.Err == syscall.EADDRNOTAVAIL | 221 return ok && e.Err == syscall.EADDRNOTAVAIL |
219 } | 222 } |
220 | 223 |
221 // TCPListener is a TCP network listener. | 224 // TCPListener is a TCP network listener. |
222 // Clients should typically use variables of type Listener | 225 // Clients should typically use variables of type Listener |
223 // instead of assuming TCP. | 226 // instead of assuming TCP. |
224 type TCPListener struct { | 227 type TCPListener struct { |
225 fd *netFD | 228 fd *netFD |
226 } | 229 } |
227 | 230 |
228 // ListenTCP announces on the TCP address laddr on the network net, | 231 // AcceptTCP accepts the next incoming call and returns the new connection |
229 // which must be "tcp", "tcp4" or "tcp6" and returns a TCP listener. | 232 // and the remote address. |
230 // If laddr has a port of 0, it means to listen on some available | 233 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) { |
231 // port. The caller can use Addr() of TCPListener to retrieve the | 234 » if l == nil || l.fd == nil || l.fd.sysfd < 0 { |
232 // chosen address. | 235 » » return nil, syscall.EINVAL |
| 236 » } |
| 237 » fd, err := l.fd.accept(sockaddrToTCP) |
| 238 » if err != nil { |
| 239 » » return nil, err |
| 240 » } |
| 241 » return newTCPConn(fd), nil |
| 242 } |
| 243 |
| 244 // Accept implements the Accept method in the Listener interface; |
| 245 // it waits for the next call and returns a generic Conn. |
| 246 func (l *TCPListener) Accept() (c Conn, err error) { |
| 247 » c1, err := l.AcceptTCP() |
| 248 » if err != nil { |
| 249 » » return nil, err |
| 250 » } |
| 251 » return c1, nil |
| 252 } |
| 253 |
| 254 // Close stops listening on the TCP address. |
| 255 // Already Accepted connections are not closed. |
| 256 func (l *TCPListener) Close() error { |
| 257 » if l == nil || l.fd == nil { |
| 258 » » return syscall.EINVAL |
| 259 » } |
| 260 » return l.fd.Close() |
| 261 } |
| 262 |
| 263 // Addr returns the listener's network address, a *TCPAddr. |
| 264 func (l *TCPListener) Addr() Addr { return l.fd.laddr } |
| 265 |
| 266 // SetDeadline sets the deadline associated with the listener. |
| 267 // A zero time value disables the deadline. |
| 268 func (l *TCPListener) SetDeadline(t time.Time) error { |
| 269 » if l == nil || l.fd == nil { |
| 270 » » return syscall.EINVAL |
| 271 » } |
| 272 » return setDeadline(l.fd, t) |
| 273 } |
| 274 |
| 275 // File returns a copy of the underlying os.File, set to blocking mode. |
| 276 // It is the caller's responsibility to close f when finished. |
| 277 // Closing l does not affect f, and closing f does not affect l. |
| 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. |
233 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { | 284 func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) { |
234 switch net { | 285 switch net { |
235 case "tcp", "tcp4", "tcp6": | 286 case "tcp", "tcp4", "tcp6": |
236 default: | 287 default: |
237 return nil, UnknownNetworkError(net) | 288 return nil, UnknownNetworkError(net) |
238 } | 289 } |
239 if laddr == nil { | 290 if laddr == nil { |
240 » » return nil, &OpError{"listen", net, nil, errMissingAddress} | 291 » » laddr = &TCPAddr{} |
241 » } | 292 » } |
242 » fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM,
0, "listen", sockaddrToTCP) | 293 » fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.
SOCK_STREAM, 0, "listen", sockaddrToTCP) |
243 if err != nil { | 294 if err != nil { |
244 return nil, err | 295 return nil, err |
245 } | 296 } |
246 err = syscall.Listen(fd.sysfd, listenerBacklog) | 297 err = syscall.Listen(fd.sysfd, listenerBacklog) |
247 if err != nil { | 298 if err != nil { |
248 closesocket(fd.sysfd) | 299 closesocket(fd.sysfd) |
249 return nil, &OpError{"listen", net, laddr, err} | 300 return nil, &OpError{"listen", net, laddr, err} |
250 } | 301 } |
251 l := new(TCPListener) | 302 l := new(TCPListener) |
252 l.fd = fd | 303 l.fd = fd |
253 return l, nil | 304 return l, nil |
254 } | 305 } |
255 | |
256 // AcceptTCP accepts the next incoming call and returns the new connection | |
257 // and the remote address. | |
258 func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) { | |
259 if l == nil || l.fd == nil || l.fd.sysfd < 0 { | |
260 return nil, syscall.EINVAL | |
261 } | |
262 fd, err := l.fd.accept(sockaddrToTCP) | |
263 if err != nil { | |
264 return nil, err | |
265 } | |
266 return newTCPConn(fd), nil | |
267 } | |
268 | |
269 // Accept implements the Accept method in the Listener interface; | |
270 // it waits for the next call and returns a generic Conn. | |
271 func (l *TCPListener) Accept() (c Conn, err error) { | |
272 c1, err := l.AcceptTCP() | |
273 if err != nil { | |
274 return nil, err | |
275 } | |
276 return c1, nil | |
277 } | |
278 | |
279 // Close stops listening on the TCP address. | |
280 // Already Accepted connections are not closed. | |
281 func (l *TCPListener) Close() error { | |
282 if l == nil || l.fd == nil { | |
283 return syscall.EINVAL | |
284 } | |
285 return l.fd.Close() | |
286 } | |
287 | |
288 // Addr returns the listener's network address, a *TCPAddr. | |
289 func (l *TCPListener) Addr() Addr { return l.fd.laddr } | |
290 | |
291 // SetDeadline sets the deadline associated with the listener. | |
292 // A zero time value disables the deadline. | |
293 func (l *TCPListener) SetDeadline(t time.Time) error { | |
294 if l == nil || l.fd == nil { | |
295 return syscall.EINVAL | |
296 } | |
297 return setDeadline(l.fd, t) | |
298 } | |
299 | |
300 // File returns a copy of the underlying os.File, set to blocking mode. | |
301 // It is the caller's responsibility to close f when finished. | |
302 // Closing l does not affect f, and closing f does not affect l. | |
303 func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() } | |
LEFT | RIGHT |