ソースを参照

tcp-nodelay patch by Joe Halpin

Daniel Stenberg 20 年 前
コミット
bb3d6e8552
7 ファイル変更70 行追加1 行削除
  1. 6 1
      docs/curl.1
  2. 16 0
      docs/libcurl/curl_easy_setopt.3
  3. 3 0
      include/curl/curl.h
  4. 24 0
      lib/connect.c
  5. 8 0
      lib/url.c
  6. 3 0
      lib/urldata.h
  7. 10 0
      src/main.c

+ 6 - 1
docs/curl.1

@@ -2,7 +2,7 @@
 .\" nroff -man curl.1
 .\" Written by Daniel Stenberg
 .\"
-.TH curl 1 "5 Mar 2004" "Curl 7.11.1" "Curl Manual"
+.TH curl 1 "25 Mar 2004" "Curl 7.11.2" "Curl Manual"
 .SH NAME
 curl \- transfer a URL
 .SH SYNOPSIS
@@ -707,6 +707,11 @@ is a plain '-', it is instead written to stdout. This option has no point when
 you're using a shell with decent redirecting capabilities.
 
 If this option is used several times, the last one will be used.
+.IP "--tcp-nodelay"
+Turn on the TCP_NODELAY option. See the \fIcurl_easy_setopt(3)\fP man page for
+details about this option. (Added in 7.11.2)
+
+If this option is used several times, each occurance toggles this on/off.
 .IP "-t/--telnet-option <OPT=val>"
 Pass options to the telnet protocol. Supported options are:
 

+ 16 - 0
docs/libcurl/curl_easy_setopt.3

@@ -295,6 +295,22 @@ cannot be guaranteed to actually get the given size. (Added in 7.10)
 .IP CURLOPT_PORT
 Pass a long specifying what remote port number to connect to, instead of the
 one specified in the URL or the default port for the used protocol.
+.IP CURLOPT_TCP_NODELAY
+Pass a long specifying whether the TCP_NODELAY option should be set or
+cleared (1 = set, 0 = clear). The option is cleared by default. This
+will have no effect after the connection has been established.
+
+Setting this option will disable TCP's Nagle algorithm. The purpose of
+this algorithm is to try to minimize the number of small packets on
+the network (where "small packets" means TCP segments less than the
+Maximum Segment Size (MSS) for the network).
+
+Maximizing the amount of data sent per TCP segment is good because it
+amortizes the overhead of the send. However, in some cases (most
+notably telnet or rlogin) small segments may need to be sent
+without delay. This is less efficient than sending larger amounts of
+data at a time, and can contribute to congestion on the network if
+overdone. 
 .SH NAMES and PASSWORDS OPTIONS (Authentication)
 .IP CURLOPT_NETRC
 This parameter controls the preference of libcurl between using user names and

+ 3 - 0
include/curl/curl.h

@@ -762,6 +762,9 @@ typedef enum {
   /* The _LARGE version of the standard POSTFIELDSIZE option */
   CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
 
+  /* Enable/disable the TCP Nagle algorithm */
+  CINIT(TCP_NODELAY, LONG, 121),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 

+ 24 - 0
lib/connect.c

@@ -31,6 +31,7 @@
 #endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#include <netinet/tcp.h> /* for TCP_NODELAY */
 #endif
 #include <sys/ioctl.h>
 #ifdef HAVE_UNISTD_H
@@ -476,6 +477,23 @@ CURLcode Curl_is_connected(struct connectdata *conn,
   return CURLE_OK;
 }
 
+static void Curl_setNoDelay(struct connectdata *conn,
+                            curl_socket_t sockfd,
+                            int ip)
+{
+#ifdef TCP_NODELAY
+  struct SessionHandle *data= conn->data;
+  socklen_t onoff = (socklen_t) data->tcp_nodelay;
+  infof(data,"Setting TCP_NODELAY for IPv%d\n", ip);
+  if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &onoff, sizeof(onoff)) < 0)
+    infof(data, "Could not set TCP_NODELAY: %s\n",
+          Curl_strerror(conn, Curl_ourerrno()));
+#else
+  (void)conn;
+  (void)sockfd;
+  (void)ip;
+#endif
+}
 
 /*
  * TCP connect to the given host with timeout, proxy or remote doesn't matter.
@@ -554,6 +572,9 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
     sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
     if (sockfd == CURL_SOCKET_BAD)
       continue;
+
+    else if(data->tcp_nodelay)
+      Curl_setNoDelay(conn, sockfd, 6);
 #else
   /*
    * Connecting with old style IPv4-only support
@@ -573,6 +594,9 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
       return CURLE_COULDNT_CONNECT; /* big time error */
     }
 
+    else if(data->tcp_nodelay)
+      Curl_setNoDelay(conn, sockfd, 4);
+
     /* nasty address work before connect can be made */
     memset((char *) &serv_addr, '\0', sizeof(serv_addr));
     memcpy((char *)&(serv_addr.sin_addr),

+ 8 - 0
lib/url.c

@@ -1303,6 +1303,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
     data->set.max_filesize = va_arg(param, curl_off_t);
     break;
 
+  case CURLOPT_TCP_NODELAY:
+    /*
+     * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
+     * algorithm
+     */
+    data->tcp_nodelay = va_arg(param, long);
+    break;
+
   default:
     /* unknown tag and its companion, just ignore: */
     return CURLE_FAILED_INIT; /* correct this */

+ 3 - 0
lib/urldata.h

@@ -908,6 +908,9 @@ struct SessionHandle {
 #if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
   ENGINE*  engine;
 #endif /* USE_SSLEAY */
+
+  /* This tells CreateConnection() whether to enable TCP_NODELAY or not */
+  int tcp_nodelay;
 };
 
 #define LIBCURL_NAME "libcurl"

+ 10 - 0
src/main.c

@@ -294,6 +294,7 @@ static void help(void)
     "    --disable-epsv  Prevent curl from using EPSV (F)",
     " -D/--dump-header <file> Write the headers to this file",
     "    --egd-file <file> EGD socket path for random data (SSL)",
+    "    --tcp-nodelay   Set the TCP_NODELAY option",
 #ifdef USE_ENVIRONMENT
     "    --environment   Write result codes to environment variables (RISC OS)",
 #endif
@@ -506,6 +507,8 @@ struct Configurable {
   bool ftp_ssl;
 
   char *socks5proxy;
+
+  bool tcp_nodelay;
 };
 
 /* global variable to hold info about libcurl */
@@ -1140,6 +1143,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     {"$a", "ftp-ssl",    FALSE},
     {"$b", "ftp-pasv",   FALSE},
     {"$c", "socks5",     TRUE},
+    {"$d", "tcp-nodelay",FALSE},
     {"0", "http1.0",     FALSE},
     {"1", "tlsv1",       FALSE},
     {"2", "sslv2",       FALSE},
@@ -1463,6 +1467,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
       case 'c': /* --socks specifies a socks5 proxy to use */
         GetStr(&config->socks5proxy, nextarg);
         break;
+      case 'd': /* --tcp-nodelay option */
+	config->tcp_nodelay ^= TRUE;
+	break;
       }
       break;
     case '#': /* added 19990617 larsa */
@@ -3112,6 +3119,9 @@ operate(struct Configurable *config, int argc, char *argv[])
         }
 #endif
 
+	if(1 == config->tcp_nodelay)
+	  curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
+
         curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine);
         curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);