HttpWebRequest and Reusing Connections

Discussion in 'ASP .Net' started by Mike, Jun 10, 2010.

  1. Mike

    Mike Guest

    Hi, I need to modify an existing Windows forms application that (among
    many other things) uploads files from the users machine to the web
    server which is on the same domain. On the server there is a "Generic
    Handler" / .ashx that receive the files. The current implementation
    uploads files in one shot as a single byte array, which for very large
    files (100's of MBs) is prone to OutOfMemoryExceptions anywhere in the
    process, both client and server side. So instead we need to upload the
    files in more manageable "chunks".

    The code below reads and uploads files 64 KB at a time. It works
    except for one big problem. As it's running, it appears from netstat
    output that each HttpWebRequest ties up a distinct port on the client
    with a status of TIME_WAIT. After about 4,000 or so requests I get
    this error on the client:

    WebException was unhandled
    Unable to connect to the remote server
    Only one usage of each socket address (protocol/network address/port)
    is normally permitted

    So this error message, together with netstat, indicates all the ports
    on the client machine are tied up. I would expect that rather than
    creating new connections for each request they would be reused based
    on the post below, but evidently they aren't:

    http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/6d67ff8b-14ff-44b0-9dcd-1c8b9d2ab42b

    Any suggestions how I can either release the port immediately after
    the request/response completes, or even better reuse the same port for
    all of the requests since they are serial/synchronous? To that end,
    I've tried using various combinations of KeepAlive,
    ConnectionGroupName, UnsafeAuthenticatedConnectionSharing, and others
    to force reuse based on other posts I've read, but I wasn't able to
    hit on the "magic" combination.

    Also, I've read about editing the registry to increase the number of
    ports available to the application, but in production I cannot do this
    on the user's machines, and besides that doesn't really seem like a
    "solution" to me.

    Thanks!
    MJ

    Code:
    
    private void TestUpload()
    {
      UploadFile(@"C:\Temp\My800MBFile.dat", "http://localhost:1776/
    UploadFile.ashx?fileId=" + Guid.NewGuid().ToString());
    }
    
    private void UploadFile(string fileName, string url)
    {
      using (FileStream fileStream = new FileStream(fileName,
    FileMode.Open, FileAccess.Read))
      {
        byte[] buffer = new byte[65536];
    
        int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
        while (bytesRead > 0)
        {
          HttpWebRequest request = (HttpWebRequest)
    WebRequest.Create(url);
          request.Method = "POST";
    
          using (Stream requestStream = request.GetRequestStream())
          {
            requestStream.Write(buffer, 0, bytesRead);
            requestStream.Close();
          }
    
          using (HttpWebResponse response = (HttpWebResponse)
    request.GetResponse())
          {
            response.Close();
          }
    
          bytesRead = fileStream.Read(buffer, 0, buffer.Length);
        }
    
        fileStream.Close();
      }
    }
    
    
    Mike, Jun 10, 2010
    #1
    1. Advertising

  2. Mike

    cubaman Guest

    On Jun 10, 1:01 am, Mike <> wrote:
    > Hi, I need to modify an existing Windows forms application that (among
    > many other things) uploads files from the users machine to the web
    > server which is on the same domain. On the server there is a "Generic
    > Handler" / .ashx that receive the files. The current implementation
    > uploads files in one shot as a single byte array, which for very large
    > files (100's of MBs) is prone to OutOfMemoryExceptions anywhere in the
    > process, both client and server side. So instead we need to upload the
    > files in more manageable "chunks".
    >
    > The code below reads and uploads files 64 KB at a time. It works
    > except for one big problem. As it's running, it appears from netstat
    > output that each HttpWebRequest ties up a distinct port on the client
    > with a status of TIME_WAIT. After about 4,000 or so requests I get
    > this error on the client:
    >
    > WebException was unhandled
    > Unable to connect to the remote server
    > Only one usage of each socket address (protocol/network address/port)
    > is normally permitted
    >
    > So this error message, together with netstat, indicates all the ports
    > on the client machine are tied up. I would expect that rather than
    > creating new connections for each request they would be reused based
    > on the post below, but evidently they aren't:
    >
    > http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/6d67ff8b-14f...
    >
    > Any suggestions how I can either release the port immediately after
    > the request/response completes, or even better reuse the same port for
    > all of the requests since they are serial/synchronous? To that end,
    > I've tried using various combinations of KeepAlive,
    > ConnectionGroupName, UnsafeAuthenticatedConnectionSharing, and others
    > to force reuse based on other posts I've read, but I wasn't able to
    > hit on the "magic" combination.
    >
    > Also, I've read about editing the registry to increase the number of
    > ports available to the application, but in production I cannot do this
    > on the user's machines, and besides that doesn't really seem like a
    > "solution" to me.
    >
    > Thanks!
    > MJ
    >
    >
    Code:
    >
    > private void TestUpload()
    > {
    >   UploadFile(@"C:\Temp\My800MBFile.dat", "http://localhost:1776/
    > UploadFile.ashx?fileId=" + Guid.NewGuid().ToString());
    >
    > }
    >
    > private void UploadFile(string fileName, string url)
    > {
    >   using (FileStream fileStream = new FileStream(fileName,
    > FileMode.Open, FileAccess.Read))
    >   {
    >     byte[] buffer = new byte[65536];
    >
    >     int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
    >     while (bytesRead > 0)
    >     {
    >       HttpWebRequest request = (HttpWebRequest)
    > WebRequest.Create(url);
    >       request.Method = "POST";
    >
    >       using (Stream requestStream = request.GetRequestStream())
    >       {
    >         requestStream.Write(buffer, 0, bytesRead);
    >         requestStream.Close();
    >       }
    >
    >       using (HttpWebResponse response = (HttpWebResponse)
    > request.GetResponse())
    >       {
    >         response.Close();
    >       }
    >
    >       bytesRead = fileStream.Read(buffer, 0, buffer.Length);
    >     }
    >
    >     fileStream.Close();
    >   }
    >
    > }
    >
    > 


    First, I would create a WCF Service instead of a ashx to handle the
    file upload. Second, i'd try to implement some kind of compression
    before uploading the file.
    Sorry, cant help with connection re-use.
    Best regards.
    cubaman, Jun 11, 2010
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dan
    Replies:
    4
    Views:
    9,449
    taylorjonl
    Jun 1, 2007
  2. Roger Binns
    Replies:
    14
    Views:
    562
    Christian Tismer
    Feb 26, 2004
  3. Steve B.
    Replies:
    3
    Views:
    866
    Steve B.
    Jul 17, 2007
  4. jobs
    Replies:
    2
    Views:
    873
  5. Steve B.

    .Net 2.0 : Soap client : reusing http connections ?

    Steve B., Jul 17, 2007, in forum: ASP .Net Web Services
    Replies:
    3
    Views:
    266
    Steve B.
    Jul 17, 2007
Loading...

Share This Page