Link to home
Start Free TrialLog in
Avatar of DaFou
DaFou

asked on

How to introduce new threads

Ola,

I wrote some code that accepts incomming TcpClients and store them. And on each incomming TcpCLient write to all already stored TcpClients some javascript that is performed on the browser client from where the underlieing HTTP request orignated. In the code I only listen for 3 clients but this is just for testing purposes.

If you want to know why I build this code and what it would do follow these 2 posts.
https://www.experts-exchange.com/questions/21057802/How-to-collect-store-and-respond-to-incomming-requests.html
https://www.experts-exchange.com/questions/21077836/Storing-stream-writers.html
the code in this question is a sollution for the problem I describe in the 2 questions above.

At some point in the code in this question I want to start a new thread that listens for additional TcpClients how can this be done.

Ill be on holliday until 16 aug so there is some time for you experts to figure out what is needed :-)

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.IO;
using System.Text;

namespace AtomHTTPresponse
{
      class AtomHTTPresponse
      {
            private ArrayList lObjArrayList = new ArrayList();
            static void Main(string[] args)
            {
                  AtomHTTPresponse lObjAtomHTTPresponse = new AtomHTTPresponse();
                  IPAddress IPAddressLocal = IPAddress.Parse( "127.0.0.1" );
                  TcpListener lTcpListner = new TcpListener( IPAddressLocal, 9999 );

                  lTcpListner.Start();
               
                  for ( int lCntOuter = 0; lCntOuter < 3; lCntOuter++ )
                  {
                        // waiting for an incomming TcpCLient should be done on a separte thread. So in the end there will be 3 clients connected in 3 seperate threads
                        TcpClient lTcpClient                  = lTcpListner.AcceptTcpClient();
                        NetworkStream lNetworkStream      = lTcpClient.GetStream();
                        StreamReader lStreamReader            = new StreamReader( lNetworkStream );
                        StreamWriter lStreamWriter            = new StreamWriter( lNetworkStream );

                        HTTPpipe lHTTPpipe = new HTTPpipe( lTcpClient, lNetworkStream, lStreamReader, lStreamWriter );
                        lObjAtomHTTPresponse.lObjArrayList.Add( lHTTPpipe );
                        lHTTPpipe.WriteToCLient( "<script language=\"javascript\">window.status = 0</script>" );

                        for ( int lCntInner = 0; lCntInner < lObjAtomHTTPresponse.lObjArrayList.Count; lCntInner++ )
                        {
                              ( lObjAtomHTTPresponse.lObjArrayList[ lCntInner ] as HTTPpipe ).WriteToCLient( "<script language=\"javascript\">window.status = parseInt( window.status ) + 1</script>" );
                        }
                  }
            }
      }
      class HTTPpipe
      {
            public TcpClient puTcpClient;
            public NetworkStream puNetworkStream;
            public StreamReader puStreamReader;
            public StreamWriter puStreamWriter;
            public char[] puArrCharRequest = new char[256];

            static string cStrResponse = "<script language=\"javascript\">window.status = 0</script>";
            
            static string cStrHTTPheader = "HTTP/1.1 200 OK\r\n"
                  + "Server: Microsoft-IIS/5.0\r\n"
                  + "Date: Wed, 9 jan 2004 19:59:09 GMT\r\n"
                  + "X-Powered-By: ASP.NET\r\n"
                  + "Content-Type: text/html\r\n"
                  + "Set-Cookie: ASPSESSIONIDASQSSARR=CCOBBLCBOLKOECFIANBGOBAI; path=/\r\n" // let it be for now. redundancy will be removed at a later time
                  + "Cache-control: private\r\n\r\n";

            public HTTPpipe( TcpClient iTcpClient, NetworkStream iNetworkStream, StreamReader iStreamReader, StreamWriter iStreamWriter )
            {
                  puTcpClient            = iTcpClient;
                  puNetworkStream      = iNetworkStream;
                  puStreamReader      = iStreamReader;
                  puStreamWriter      = iStreamWriter;
                  puStreamReader.Read( puArrCharRequest, 0, puArrCharRequest.Length );
                  WriteToCLient( cStrHTTPheader );
                  WriteToCLient( cStrResponse );
            }
            public void WriteToCLient( string iStrResponse )
            {
                  puStreamWriter.Write( iStrResponse );
                  puStreamWriter.Flush();
            }
      }
}
ASKER CERTIFIED SOLUTION
Avatar of drichards
drichards

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of DaFou
DaFou

ASKER

the reason I wanted to introduce threads is because of something really weird I cannot yet explain.

When i open 3 new instances of IE and connect the first client to localhost:9999 all the status bar displays is:
"opening page......."
It does not display "1" as expected. But when the 2nd client connects the 1st client displays "2" and the 2nd client displays "opening page"
Only when the 3rd client connects the 2nd client displays "2" the first client displays "3" and the 3rd client displays "1" ( because the programm now terminated. )
But when I restart the client and reuse the same 3 clients ( without closing them and opening new instances of IE ) the first client after connecting displays "1" imediately ( as should be ).
when connecting the 2nd client it imediatly displays "1" and the 1st client dispays "2" and so on and so on.

Hmm why could this be?

WHen I use fresh instances of IE your code does not update the status bar in any case. But it does work as expexted when I reuse clients then your code works like it should.

very very weird :-(
Avatar of DaFou

ASKER

Even with the use of new threads the behvior stays the same. REALLY annoying and weird.
Although I am very excited that I got IE to listen and display stuff.

Here is the code I made with threads after your code ( unfortunately  ) did less for me then my original code.

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.IO;
using System.Text;

namespace AtomHTTPresponse
{
      class AtomHTTPresponse
      {
            private ArrayList prArrayListHTTPpipes = new ArrayList();
            private TcpListener prTcpListener = new TcpListener( IPAddress.Parse( "127.0.0.1" ), 9999 );
            static void Main(string[] args)
            {
                  AtomHTTPresponse lAtomHTTPresponse = new AtomHTTPresponse();
                  Thread lThreadListener = new Thread( new ThreadStart( lAtomHTTPresponse.ListenerHandler ) );
                  lThreadListener.Start();
            }
            private void ListenerHandler()
            {
                  prTcpListener.Start();
                  for ( int lCntOuter = 0; lCntOuter < 2; lCntOuter++ )
                  {
                        //lock ( this )
                        //{
                              Thread lThreadListener = new Thread( new ThreadStart( ConnectionHandler ) );
                              lThreadListener.Start();
                        //}
                  }
            }
            private void ConnectionHandler()
            {
                  TcpClient lTcpClient                  = prTcpListener.AcceptTcpClient();
                  NetworkStream lNetworkStream      = lTcpClient.GetStream();
                  StreamReader lStreamReader            = new StreamReader( lNetworkStream );
                  StreamWriter lStreamWriter            = new StreamWriter( lNetworkStream );

                  HTTPpipe lHTTPpipe = new HTTPpipe( lTcpClient, lNetworkStream, lStreamReader, lStreamWriter );
                  prArrayListHTTPpipes.Add( lHTTPpipe );
                  lHTTPpipe.WriteToCLient( "<script language=\"javascript\">window.status = 0</script>" );

                  for ( int lCntInner = 0; lCntInner < prArrayListHTTPpipes.Count; lCntInner++ )
                  {
                        ( prArrayListHTTPpipes[ lCntInner ] as HTTPpipe ).WriteToCLient( "<script language=\"javascript\">window.status = parseInt( window.status ) + 1</script>" );
                  }
            }
      }
      class HTTPpipe
      {
            public TcpClient puTcpClient;
            public NetworkStream puNetworkStream;
            public StreamReader puStreamReader;
            public StreamWriter puStreamWriter;
            public char[] puArrCharRequest = new char[256];

            static string cStrResponse = "<script language=\"javascript\">window.status = 0</script>";
         
            static string cStrHTTPheader = "HTTP/1.1 200 OK\r\n"
                  + "Server: Microsoft-IIS/5.0\r\n"
                  + "Date: Wed, 9 jan 2004 19:59:09 GMT\r\n"
                  + "X-Powered-By: ASP.NET\r\n"
                  + "Content-Type: text/html\r\n"
                  + "Set-Cookie: ASPSESSIONIDASQSSARR=CCOBBLCBOLKOECFIANBGOBAI; path=/\r\n" // let it be for now. redundancy will be removed at a later time
                  + "Cache-control: private\r\n\r\n";

            public HTTPpipe( TcpClient iTcpClient, NetworkStream iNetworkStream, StreamReader iStreamReader, StreamWriter iStreamWriter )
            {
                  puTcpClient                  = iTcpClient;
                  puNetworkStream            = iNetworkStream;
                  puStreamReader            = iStreamReader;
                  puStreamWriter            = iStreamWriter;
                  puStreamReader.Read( puArrCharRequest, 0, puArrCharRequest.Length );
                  WriteToCLient( cStrHTTPheader );
                  WriteToCLient( cStrResponse );
            }
            public void WriteToCLient( string iStrResponse )
            {
                  puStreamWriter.Write( iStrResponse );
                  puStreamWriter.Flush();
            }
      }
}
Avatar of DaFou

ASKER

ill accept your asnwers for your effort. please think real hard on what can couse these symptoms?
Didn't you decide you need chunked encoding for this to work properly?  I won't be able to get back to this for a couple of days, but I'll take a look if you still have not figured it out.
Avatar of DaFou

ASKER

The chunked encoding was part of the HTTP header clasic ASP sends to the client when running my proof of concept script in clasic ASP ( the script that updates the status bar every 5 seconds forever ). I used etherreal to get that HTTPheader.

But when I send that HTTP header useing the code above all IE displays is an error.
then I used some webpage to show me the HTTPheader my IIS sends and it is the HTTP header I am using now. This HTTPheader does work ( does not generate an error ) but the behavior is very weird.

I am not sure if the behavior is is caused by the HTTPheader and I cant really change the HTTPheader coz the slightes miss formatting generates and error.
And i have not found HTTPheader examples yet.

I hope this explains a bit more
Avatar of DaFou

ASKER

fixed it.

i was sending too little data to the client to make it handle it imediatly. sending some bogus HTML after the HTTP header and before the first <script> response fixes the problem. on netscape aswell.



public HTTPpipe( TcpClient iTcpClient, NetworkStream iNetworkStream, StreamReader iStreamReader, StreamWriter iStreamWriter )
          {
               puTcpClient               = iTcpClient;
               puNetworkStream          = iNetworkStream;
               puStreamReader          = iStreamReader;
               puStreamWriter          = iStreamWriter;
               puStreamReader.Read( puArrCharRequest, 0, puArrCharRequest.Length ); // do nothing with the request but now we know we dont send a response before the request has been fully received.
               WriteToClient( cStrHTTPheader );
               // the weird HTML content is to force the browser to deal with the data imediatly
               // this is where al past troubles came from leaving it out
               WriteToClient( "<html><head><title>erereerereerere erereerereerereerereerereerereerereerereerereerereerereerereerereerere erereerereerereerereerereerereerereerereerereerereerereerere</title></head><body>blha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdfblha asfdsf jhsdf</body></html>" );
               WriteToClient( cStrResponse );
          }

it looks nasty but it works
And therein lies the problem - how do you force the browser to render the partial data since it doesn't know how big the document is?  Also, is it really the length of the document or just the fact that it IS a complete document?  Is it just that the browser renders because the </html> was received (paired with the earlier <html> of course)?
Avatar of DaFou

ASKER

it is about the length of the data. i have made many web pages rendererd in tables of 100 rows and have the tables displayed before the rendering of the entire page was done. so i know IE does not wait for the </HTML>

please help out on this 500 points question
https://www.experts-exchange.com/questions/21098923/NET-Remoting-to-a-windows-service-in-NET.html