| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/tcp_client_socket.h" | 5 #include "net/base/tcp_client_socket.h" |
| 6 | 6 |
| 7 #include "base/memory_debug.h" | 7 #include "base/memory_debug.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/sys_info.h" |
| 9 #include "base/trace_event.h" | 10 #include "base/trace_event.h" |
| 10 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
| 11 #include "net/base/winsock_init.h" | 12 #include "net/base/winsock_init.h" |
| 12 | 13 |
| 13 namespace net { | 14 namespace net { |
| 14 | 15 |
| 15 //----------------------------------------------------------------------------- | 16 //----------------------------------------------------------------------------- |
| 16 | 17 |
| 17 static int MapWinsockError(DWORD err) { | 18 static int MapWinsockError(DWORD err) { |
| 18 // There are numerous Winsock error codes, but these are the ones we thus far | 19 // There are numerous Winsock error codes, but these are the ones we thus far |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 | 244 |
| 244 int TCPClientSocket::CreateSocket(const struct addrinfo* ai) { | 245 int TCPClientSocket::CreateSocket(const struct addrinfo* ai) { |
| 245 socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0, | 246 socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0, |
| 246 WSA_FLAG_OVERLAPPED); | 247 WSA_FLAG_OVERLAPPED); |
| 247 if (socket_ == INVALID_SOCKET) { | 248 if (socket_ == INVALID_SOCKET) { |
| 248 DWORD err = WSAGetLastError(); | 249 DWORD err = WSAGetLastError(); |
| 249 LOG(ERROR) << "WSASocket failed: " << err; | 250 LOG(ERROR) << "WSASocket failed: " << err; |
| 250 return MapWinsockError(err); | 251 return MapWinsockError(err); |
| 251 } | 252 } |
| 252 | 253 |
| 253 // Increase the socket buffer sizes from the default sizes. | 254 // Increase the socket buffer sizes from the default sizes for WinXP. In |
| 254 // In performance testing, there is substantial benefit by increasing | 255 // performance testing, there is substantial benefit by increasing from 8KB |
| 255 // from 8KB to 32KB. I tested 64, 128, and 256KB as well, but did not | 256 // to 64KB. |
| 256 // see additional performance benefit (will be network dependent). | |
| 257 // See also: | 257 // See also: |
| 258 // http://support.microsoft.com/kb/823764/EN-US | 258 // http://support.microsoft.com/kb/823764/EN-US |
| 259 // On XP, the default buffer sizes are 8KB. | 259 // On Vista, if we manually set these sizes, Vista turns off its receive |
| 260 const int kSocketBufferSize = 32 * 1024; | 260 // window auto-tuning feature. |
| 261 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 261 // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx |
| 262 reinterpret_cast<const char*>(&kSocketBufferSize), | 262 // Since Vista's auto-tune is better than any static value we can could set, |
| 263 sizeof(kSocketBufferSize)); | 263 // only change these on pre-vista machines. |
| 264 DCHECK(!rv) << "Could not set socket send buffer size"; | 264 int32 major_version, minor_version, fix_version; |
| 265 rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 265 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, |
| 266 reinterpret_cast<const char*>(&kSocketBufferSize), | 266 &fix_version); |
| 267 sizeof(kSocketBufferSize)); | 267 if (major_version < 6) { |
| 268 DCHECK(!rv) << "Could not set socket receive buffer size"; | 268 const int kSocketBufferSize = 64 * 1024; |
| 269 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| 270 reinterpret_cast<const char*>(&kSocketBufferSize), |
| 271 sizeof(kSocketBufferSize)); |
| 272 DCHECK(!rv) << "Could not set socket send buffer size"; |
| 273 rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| 274 reinterpret_cast<const char*>(&kSocketBufferSize), |
| 275 sizeof(kSocketBufferSize)); |
| 276 DCHECK(!rv) << "Could not set socket receive buffer size"; |
| 277 } |
| 269 | 278 |
| 270 // Disable Nagle. | 279 // Disable Nagle. |
| 271 // The Nagle implementation on windows is governed by RFC 896. The idea | 280 // The Nagle implementation on windows is governed by RFC 896. The idea |
| 272 // behind Nagle is to reduce small packets on the network. When Nagle is | 281 // behind Nagle is to reduce small packets on the network. When Nagle is |
| 273 // enabled, if a partial packet has been sent, the TCP stack will disallow | 282 // enabled, if a partial packet has been sent, the TCP stack will disallow |
| 274 // further *partial* packets until an ACK has been received from the other | 283 // further *partial* packets until an ACK has been received from the other |
| 275 // side. Good applications should always strive to send as much data as | 284 // side. Good applications should always strive to send as much data as |
| 276 // possible and avoid partial-packet sends. However, in most real world | 285 // possible and avoid partial-packet sends. However, in most real world |
| 277 // applications, there are edge cases where this does not happen, and two | 286 // applications, there are edge cases where this does not happen, and two |
| 278 // partil packets may be sent back to back. For a browser, it is NEVER | 287 // partil packets may be sent back to back. For a browser, it is NEVER |
| 279 // a benefit to delay for an RTT before the second packet is sent. | 288 // a benefit to delay for an RTT before the second packet is sent. |
| 280 // | 289 // |
| 281 // As a practical example in Chromium today, consider the case of a small | 290 // As a practical example in Chromium today, consider the case of a small |
| 282 // POST. I have verified this: | 291 // POST. I have verified this: |
| 283 // Client writes 649 bytes of header (partial packet #1) | 292 // Client writes 649 bytes of header (partial packet #1) |
| 284 // Client writes 50 bytes of POST data (partial packet #2) | 293 // Client writes 50 bytes of POST data (partial packet #2) |
| 285 // In the above example, with Nagle, a RTT delay is inserted between these | 294 // In the above example, with Nagle, a RTT delay is inserted between these |
| 286 // two sends due to nagle. RTTs can easily be 100ms or more. The best | 295 // two sends due to nagle. RTTs can easily be 100ms or more. The best |
| 287 // fix is to make sure that for POSTing data, we write as much data as | 296 // fix is to make sure that for POSTing data, we write as much data as |
| 288 // possible and minimize partial packets. We will fix that. But disabling | 297 // possible and minimize partial packets. We will fix that. But disabling |
| 289 // Nagle also ensure we don't run into this delay in other edge cases. | 298 // Nagle also ensure we don't run into this delay in other edge cases. |
| 290 // See also: | 299 // See also: |
| 291 // http://technet.microsoft.com/en-us/library/bb726981.aspx | 300 // http://technet.microsoft.com/en-us/library/bb726981.aspx |
| 292 const BOOL kDisableNagle = TRUE; | 301 const BOOL kDisableNagle = TRUE; |
| 293 rv = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, | 302 int rv = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, |
| 294 reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle)); | 303 reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle)); |
| 295 DCHECK(!rv) << "Could not disable nagle"; | 304 DCHECK(!rv) << "Could not disable nagle"; |
| 296 | 305 |
| 297 return OK; | 306 return OK; |
| 298 } | 307 } |
| 299 | 308 |
| 300 void TCPClientSocket::DoCallback(int rv) { | 309 void TCPClientSocket::DoCallback(int rv) { |
| 301 DCHECK(rv != ERR_IO_PENDING); | 310 DCHECK(rv != ERR_IO_PENDING); |
| 302 DCHECK(callback_); | 311 DCHECK(callback_); |
| 303 | 312 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 void TCPClientSocket::WaitForAndResetEvent() { | 388 void TCPClientSocket::WaitForAndResetEvent() { |
| 380 // TODO(wtc): Remove the CHECKs after enough testing. | 389 // TODO(wtc): Remove the CHECKs after enough testing. |
| 381 DWORD wait_rv = WaitForSingleObject(overlapped_.hEvent, INFINITE); | 390 DWORD wait_rv = WaitForSingleObject(overlapped_.hEvent, INFINITE); |
| 382 CHECK(wait_rv == WAIT_OBJECT_0); | 391 CHECK(wait_rv == WAIT_OBJECT_0); |
| 383 BOOL ok = WSAResetEvent(overlapped_.hEvent); | 392 BOOL ok = WSAResetEvent(overlapped_.hEvent); |
| 384 CHECK(ok); | 393 CHECK(ok); |
| 385 } | 394 } |
| 386 | 395 |
| 387 } // namespace net | 396 } // namespace net |
| 388 | 397 |
| OLD | NEW |