0

I know this has been asked before but my case is different. because i have no idea what the following code does. i am just using it as third party open source tool.

I am using open source tool "UnityHTTP" to get response from server. I would like to get response request cancelled if it is taking a long time.

I am not an expert of C# so i couldn't understand what's going on inside the code the tool provided.

I'd appreciate if someone could help me out here.

the code for getting response is as follows

    private void GetResponse() {
        System.Diagnostics.Stopwatch curcall = new System.Diagnostics.Stopwatch();
        curcall.Start();
        try {

            var retry = 0;
            while (++retry < maximumRetryCount) {
                if (useCache) {
                    string etag = "";
                    if (etags.TryGetValue (uri.AbsoluteUri, out etag)) {
                        SetHeader ("If-None-Match", etag);
                    }
                }

                SetHeader ("Host", uri.Host);

                var client = new TcpClient ();
                client.Connect (uri.Host, uri.Port);
                using (var stream = client.GetStream ()) {
                    var ostream = stream as Stream;
                    if (uri.Scheme.ToLower() == "https") {
                        ostream = new SslStream (stream, false, new RemoteCertificateValidationCallback (ValidateServerCertificate));
                        try {
                            var ssl = ostream as SslStream;
                            ssl.AuthenticateAsClient (uri.Host);
                        } catch (Exception e) {
                            Debug.LogError ("Exception: " + e.Message);
                            return;
                        }
                    }
                    WriteToStream (ostream);
                    response = new Response ();
                    response.request = this;
                    state = RequestState.Reading;
                    response.ReadFromStream(ostream);
                }
                client.Close ();

                switch (response.status) {
                case 307:
                case 302:
                case 301:
                    uri = new Uri (response.GetHeader ("Location"));
                    continue;
                default:
                    retry = maximumRetryCount;
                    break;
                }
            }
            if (useCache) {
                string etag = response.GetHeader ("etag");
                if (etag.Length > 0)
                    etags[uri.AbsoluteUri] = etag;
            }

        } catch (Exception e) {
            Console.WriteLine ("Unhandled Exception, aborting request.");
            Console.WriteLine (e);
            exception = e;
            response = null;
        }
        state = RequestState.Done;
        isDone = true;
        responseTime = curcall.ElapsedMilliseconds;

        if ( completedCallback != null )
        {
            if (synchronous) {
                completedCallback(this);
            } else {
                // we have to use this dispatcher to avoid executing the callback inside this worker thread
                ResponseCallbackDispatcher.Singleton.requests.Enqueue( this );
            }
        }

        if ( LogAllRequests )
        {
#if !UNITY_EDITOR
            System.Console.WriteLine("NET: " + InfoString( VerboseLogging ));
#else
            if ( response != null && response.status >= 200 && response.status < 300 )
            {
                Debug.Log( InfoString( VerboseLogging ) );
            }
            else if ( response != null && response.status >= 400 )
            {
                Debug.LogError( InfoString( VerboseLogging ) );
            }
            else
            {
                Debug.LogWarning( InfoString( VerboseLogging ) );
            }
#endif
        }           
    }

I can see that it something has to do with the following line lines:-

 System.Diagnostics.Stopwatch curcall = new System.Diagnostics.Stopwatch();
        curcall.Start(); 
Pawan Joshi
  • 1,581
  • 3
  • 20
  • 40

1 Answers1

1

The request is being made using the TcpClient class. It has a two properties ReceiveTimeout and SendTimeout. After the TcpClient has been initialized, set the a desired value for both of these properties before the connection is made:

var client = new TcpClient ();
client.ReceiveTimeout = 2000; // 2 seconds
client.SendTimeout = 2000;    // 2 seconds

Doing this will cause the TcpClient to automatically cancel the request when the timeout has reached.

FYI - The below is only used for measurement of how long the request took.

 System.Diagnostics.Stopwatch curcall = new System.Diagnostics.Stopwatch();
 curcall.Start(); 
 ...
 responseTime = curcall.ElapsedMilliseconds;
Adrian Sanguineti
  • 2,455
  • 1
  • 27
  • 29
  • So does it means the total timeout will be 4 seconds, (send + recieve)? – Pawan Joshi Oct 17 '14 at 06:57
  • In the above example, yes the maximum total time the TcpClient will wait for will be 4 seconds. There is not a single timeout setting in the TcpClient client class because the send and receive are treated as two discrete operations. – Adrian Sanguineti Oct 17 '14 at 07:18
  • Also I should mention that client.Connect(host, port) will not respect these timeout values, so if the long wait is happening here, the code will still block. Have a look at these two examples if you want to implement a Connect with a timeout: http://stackoverflow.com/questions/17118632/how-to-set-the-timeout-for-a-tcpclient http://www.splinter.com.au/opening-a-tcp-connection-in-c-with-a-custom-t/ – Adrian Sanguineti Oct 17 '14 at 07:32
  • well.. as described in those answers, I have to use asynchronous request which i can't use because in my case the execution of the code has to freeze when communication from server. thats why i used synchronous request. – Pawan Joshi Oct 27 '14 at 15:43
  • Well actually that is not true. An asynchronous request just means that the main thread has the ability to do other things whilst the request is made on another thread. If you read the solutions provided in both of those answers, they are making an asynchronous request but then using their ability to do other things in order to create a timer mechanism to count how long it has been since the request has made. If the request is longer than the threshold, they terminate the request thread, otherwise they return the connection. This makes them synchronous and therefore suitable for your needs. – Adrian Sanguineti Oct 27 '14 at 21:15
  • Ok.. i'll tell you my case. why i used synchronous request in the first place. I was calling a request in one line and the response was in string format. now in the next line i was collecting that response in a string variable. since the response was taking some time to get recieved and the next line was being executed. this leaded to string varrible to be holding null value.(if i used asynchronous). so to overcome this problem i used synchronous request. this way the next line didn't get executed untill i recived full response. Do you think those answer would still be suitable ? – Pawan Joshi Oct 28 '14 at 05:29
  • Yes because only the initial connection in both answers is done asynchronously. Once the connection has been established, you still need to get the stream by calling `client.GetStream()` for making requests and have a choice of doing that synchronously by calling the synchronous read/write methods on the stream, or asynchronously by calling the stream's asynchronous read/write methods. – Adrian Sanguineti Oct 28 '14 at 05:39
  • **"...this leaded to string varrible to be holding null value."** This is because with asynchronous methods you have to tell you code to wait for the async method to complete before continuing. See [Stream.ReadAsync Method](http://msdn.microsoft.com/en-us/library/hh137813(v=vs.110).aspx) on MSDN for example of this being done using the `async` and `await` keywords. [Asynchronous programming with Async and Await](http://msdn.microsoft.com/en-us/library/hh191443.aspx) – Adrian Sanguineti Oct 28 '14 at 05:45
  • Also have a read of [Task-based Asynchronous Pattern (TAP)](http://msdn.microsoft.com/en-us/library/hh873175(v=vs.110).aspx). – Adrian Sanguineti Oct 28 '14 at 05:52