Simple Java Proxy Servlet Using HttpURLConnection

Aim
The aim of this is to create a simple Java Proxy Servlet using HttpURLConnection. About 75 lines of code only. How simple is that!? The java servlet is deployed to the 'root' context of any java container such as Glassfish or Tomcat. You have to configure your web browser proxy settings to point to the host and port where the servlet is deployed. The java source code is available through a link below. Please leave any question or comments at the end and I will endeavour to answer them.

Assumptions
This article assumes that you have Glassfish or Tomcat or an equivalent java container installed and configured. This is a basic proxy and does not cover some features such as https etc.

Versions used in this example
Sofware/Component
Image
Windows XP SP2
N/A
Glassfish
N/A
Java JDK 1.5.0
N/A
Links to these files can be found here

For the purposes of this tutorial the files are stored in the structure below. The ServletProxy directory is the working directory. You can ignore the buil.xml and passwords.txt file as these are not required to compile the example. However, if you have glassfish and ant installed you can use the build.xml file.

ServletProxy
_|_web_bin
_|__|_WEB-INF
_|__|__|_web.xml
_|__|__|_classes
_|_web_src
_|__|_myproxy
_|__|__|_MyProxy.java
_|_build.xml
_|_passwords.txt

You can download the zipped example here.

Create and deploy the Service
  1. Write and save the code below as myproxy/MyProxy.java in the web_src directory. This is the MyProxy servlet class. It recreates the url and uses HttpURLConnection to fetch the data from the requested host. As you can see the servlet request headers are copied to the outgoing HttpURLConnection headers, and incomming HttpURLConnection headers are copied back to the servlet response. This way we don't have to mess around with any headers.
     1. package myproxy;
     2. 
     3. import java.io.*;
     4. import java.util.Enumeration;
     5. import java.util.Iterator;
     6. import java.util.Map;
     7. import java.util.List;
     8. import java.util.logging.*;
     9. 
    10. import javax.servlet.*;
    11. import javax.servlet.http.*;
    12. 
    13. import java.net.URL;
    14. import java.net.HttpURLConnection;
    15. 
    16. public class MyProxy extends HttpServlet {
    17.     
    18.     private ServletContext servletContext;
    19.     private Logger log;
    20.     
    21.     public void init(ServletConfig servletConfig) throws ServletException {
    22.         servletContext = servletConfig.getServletContext();
    23.         log = Logger.getLogger(MyProxy.class.getName());
    24.     }
    25.     
    26.     public void doGet(HttpServletRequest request, HttpServletResponse response){
    27.         doPost(request, response);
    28.     }
    29. 
    30.     public void doPost(HttpServletRequest request, HttpServletResponse response){
    31. 
    32.         BufferedInputStream webToProxyBuf = null;
    33.         BufferedOutputStream proxyToClientBuf = null;
    34.         HttpURLConnection con;
    35.         
    36.         try{
    37.             int statusCode;
    38.             int oneByte;
    39.             String methodName;
    40.             String headerText;
    41.             
    42.             String urlString = request.getRequestURL().toString();
    43.             String queryString = request.getQueryString();
    44.             
    45.             urlString += queryString==null?"":"?"+queryString;
    46.             URL url = new URL(urlString);
    47.             
    48.             log.info("Fetching >"+url.toString());
    49.             
    50.             con =(HttpURLConnection) url.openConnection();
    51.             
    52.             methodName = request.getMethod();
    53.             con.setRequestMethod(methodName);
    54.             con.setDoOutput(true);
    55.             con.setDoInput(true);
    56.             con.setFollowRedirects(false);
    57.             con.setUseCaches(true);
    58. 
    59.             for( Enumeration e = request.getHeaderNames() ; e.hasMoreElements();){
    60.                 String headerName = e.nextElement().toString();
    61.                 con.setRequestProperty(headerName,    request.getHeader(headerName));
    62.             }
    63. 
    64.             con.connect();
    65.             
    66.             if(methodName.equals("POST")){
    67.                 BufferedInputStream clientToProxyBuf = new BufferedInputStream(request.getInputStream());
    68.                 BufferedOutputStream proxyToWebBuf     = new BufferedOutputStream(con.getOutputStream());
    69.                 
    70.                 while ((oneByte = clientToProxyBuf.read()) != -1) 
    71.                     proxyToWebBuf.write(oneByte);
    72.                 
    73.                 proxyToWebBuf.flush();
    74.                 proxyToWebBuf.close();
    75.                 clientToProxyBuf.close();
    76.             }
    77.             
    78.             statusCode = con.getResponseCode();
    79.             response.setStatus(statusCode);
    80.             
    81.             for( Iterator i = con.getHeaderFields().entrySet().iterator() ; i.hasNext() ;){
    82.                 Map.Entry mapEntry = (Map.Entry)i.next();
    83.                 if(mapEntry.getKey()!=null)
    84.                     response.setHeader(mapEntry.getKey().toString(), ((List)mapEntry.getValue()).get(0).toString());
    85.             }
    86.             
    87.             webToProxyBuf = new BufferedInputStream(con.getInputStream());
    88.             proxyToClientBuf = new BufferedOutputStream(response.getOutputStream());
    89. 
    90.             while ((oneByte = webToProxyBuf.read()) != -1) 
    91.                 proxyToClientBuf.write(oneByte);
    92. 
    93.             proxyToClientBuf.flush();
    94.             proxyToClientBuf.close();
    95. 
    96.             webToProxyBuf.close();
    97.             con.disconnect();
    98.             
    99.         }catch(Exception e){
    100.             System.out.println(e.getMessage());
    101.             e.printStackTrace();
    102.         }
    103.         finally{
    104.         }
    105.     }
    106. }
    Hide line numbers

  2. Now cd into the web_src directory and compile the source. Replace the path to Glassfish's lib directory with your local path. This could be lib in tomcat or any servlet container.

    ..ServletProxy\web_src>javac myproxy\MyProxy.java -d ..\web_bin\WEB-INF\classes -extdirs d:\downloads\glassfish\lib

  3. Write the web.xml file and save in under the web_bin/WEB-INF directory.
     1. <?xml version="1.0" encoding="ISO-8859-1"?>
     2. <web-app>
     3.     <servlet>
     4.         <servlet-name>My Proxy</servlet-name>
     5.         <servlet-class>myproxy.MyProxy</servlet-class>
     6.     </servlet>
     7. 
     8.     <servlet-mapping>
     9.         <servlet-name>My Proxy</servlet-name>
    10.         <url-pattern>/</url-pattern>
    11.     </servlet-mapping>
    12. </web-app>
    Hide line numbers

  4. Now create the war file. Cd into the web_bin directory and jar it all up.

    ..ServletProxy\web_bin>jar -cvf proxywala.war *

  5. Finally deploy this war file in the servlet container of your choice. Remember it has to be in the ROOT context! .

    For glassfish you can specify the root context in the admin console. The steps for glassfish are.
    1. Login to the glassfish console
    2. Navigate to Applications -> Web Applications.
    3. Select deploy.
    4. Under "location" navigate to the war file we created proxywala.war.
    5. Under "Context Root" type in "/".
    6. Click Ok.

    For tomcat the steps are
    1. Copy the contents of the web_bin directory. Make sure it's the contents only such as WEB-INF and web.xml etc. Do not copy the web_bin directory itself.
    2. Now paste the contents into the tomcat webapps/ROOT directory.
    3. Restart Tomcat - if required.

Testing the filter
  1. First change your proxy settings to point to the proxy. In this example the servlet is deployed on the localhost at port 80.
    Proxy http://localhost
    proxy Port 80

  2. Now navigate to a some sites in your brower. You will be going to the web from your proxy. This proxy needs direct internet access.

Modifying and Uncommitting Java Filter Response

Aim
The aim of this tutorial is to be able to stop a response from being committed even after doFilter is called so we can redirect the response depending on an error. Strictly speaking you cannot uncommit a response. All you can do is prevent it from getting committed. For example if there is a 404 Error, this allows you to detect this error and change the html text or redirect the response without causing the dreaded IllegalStateException? Please leave any question or comments at the end and I will endeavour to answer them.

Assumptions
This article assumes that you have Glassfish or Tomcat or an equivalent java container installed and configured.

Versions used in this example
Sofware/Component
Image
Windows XP SP2
N/A
Glassfish
N/A
JDK 1.5.0
N/A
Links to these files can be found here

For the purposes of this tutorial the files are stored in the structure below. The FilterModifyResponse directory is the working directory.

FilterExample
_|_web_bin
_|__|_index.html
_|__|_WEB-INF
_|__|__|_web.xml
_|__|__|_classes
_|__|_filtered
_|__|__|_index.html
_|_web_src
_|__|_myfilter
_|__|__|_MyFilter.java
_|__|__|_FilterServletResponseWrapper.java

Create and deploy the Service
  1. Write the Response Wrapper that will prevent the Errors from being Committed and will also allow us to extract the error. Save this file as FilterServletResponseWrapper under the web_src/myfilter directory. As you can see the sendError and flushBuffer functions do not call the parent functions. We save the error code as httpStatus and this can be got at anytime using getStatus.
     1. package myfilter;
     2. 
     3. import javax.servlet.http.HttpServletResponse;
     4. import javax.servlet.http.HttpServletResponseWrapper;
     5. 
     6. import java.io.*;
     7. 
     8. public class FilterServletResponseWrapper extends HttpServletResponseWrapper{
     9. 
    10.     private int httpStatus;
    11.     
    12.     public FilterServletResponseWrapper(HttpServletResponse response){
    13.         super(response);
    14.         httpStatus = HttpServletResponseWrapper.SC_OK;
    15.     }
    16. 
    17.     public void sendError(int sc) throws IOException {
    18.         //super.sendError(sc);
    19.         httpStatus = sc;
    20.     }
    21.     public void sendErrorEx(int sc) throws IOException {
    22.         httpStatus = sc;
    23.         super.sendError(sc);
    24.     }
    25.     
    26.     
    27.     public void setStatus(int sc){
    28.         super.setStatus(sc);
    29.         httpStatus = sc;
    30.     }
    31.     public int getStatus(){
    32.         return httpStatus;
    33.     }
    34.     
    35.     public void flushBuffer(){
    36.         //super.flushBuffer();
    37.     }
    38.     public void flushBufferEx() throws IOException {
    39.         super.flushBuffer();
    40.     }
    41. }
    Hide line numbers

  2. Write the Filter and save it as MyFilter.java in the web_src/myfilter directory. As you can see, it tests the http status by calling getStatus(). If there is an error then we redirect
     1. package myfilter;
     2. 
     3. import java.io.IOException;
     4. import javax.servlet.*;
     5. import javax.servlet.http.HttpServletRequest;
     6. import javax.servlet.http.HttpServletResponse;
     7. import javax.servlet.http.HttpServletResponseWrapper;
     8. import javax.servlet.http.HttpSession;
     9. 
    10. import java.util.logging.*;
    11. 
    12. 
    13. public class MyFilter implements javax.servlet.Filter {
    14.     private ServletContext servletContext;
    15.     private Logger log;
    16.     
    17.     public MyFilter(){
    18.         super();
    19.     }
    20.     
    21.     public void init(FilterConfig filterConfig) throws ServletException {
    22.         servletContext = filterConfig.getServletContext();
    23.         log = Logger.getLogger(MyFilter.class.getName());
    24.     }
    25. 
    26.     public void doFilter(   ServletRequest req, 
    27.                             ServletResponse res, 
    28.                             FilterChain filterChain)
    29.         throws IOException, ServletException {
    30. 
    31.         HttpServletRequest httpReq    = (HttpServletRequest)req;
    32.         FilterServletResponseWrapper httpRes   = 
    33.                                         new FilterServletResponseWrapper((HttpServletResponse)res);
    34.         
    35.         filterChain.doFilter(httpReq, httpRes);
    36.         if(httpRes.getStatus() !=  HttpServletResponseWrapper.SC_OK)
    37.             httpRes.sendRedirect("http://www.google.com");
    38.             
    39.     }
    40. 
    41.     public void destroy(){
    42.     }
    43. 
    44. }
    Hide line numbers

  3. Now cd into the web_src directory and compile the source. Replace the path to Glassfish's lib directory with your local path. This could be lib in tomcat or any servlet container.

    ..FilterModifyResponse\web_src>javac myfilter\MyFilter.java -d ..\web_bin\WEB-INF\classes -extdirs d:\downloads\glassfish\lib

  4. Now create the web.xml file which will have our filter mapping. Save this under the WEB-INF directory under web_bin. Ignore the init parameters as this is not used in this example.
     1. <?xml version="1.0" encoding="ISO-8859-1"?>
     2. 
     3. <web-app>
     4. 
     5.    <!-- Define servlet-mapped and path-mapped example filters -->
     6.     <filter>
     7.         <filter-name>My Filter</filter-name>
     8.         <filter-class>myfilter.MyFilter</filter-class>
     9.         <init-param>
    10.             <param-name>Redirect-Page</param-name>
    11.             <param-value>http://www.google.com</param-value>
    12.         </init-param>
    13.     </filter>
    14. 
    15.     <!-- Define filter mappings for the defined filters -->
    16.     <filter-mapping>
    17.         <filter-name>My Filter</filter-name>
    18.         <url-pattern>/filtered/*</url-pattern>
    19.     </filter-mapping>
    20. 
    21. </web-app>
    Hide line numbers
    As you can see the filter will intercept any url starting with "/filter/*"

  5. now create a simple index.html file and save one copy in the web_bin directory and one in the web_bin/filtered directory.
     1. <html>
     2. <head></head>
     3. <body>
     4. <h1>Test</h1>
     5. </body>
     6. </html>
    Hide line numbers

  6. Now create the war file. Cd into the web_bin directory and jar it all up.

    ..FilterModifyResponse\web_bin>jar -cvf myfilter.war *

  7. Finally deploy this war file in the servlet container of your choice. Glassfish in this example.

Testing the filter
  1. First navigate to
    http://localhost:8080/myfilter/filtered/index.html.
    No change as the html is just served up.

  2. Now navigate to
    http://localhost:8080/myfilter/filtered/index2.html.
    Instead of getting the standard 404 file not found error, you will be redirected to http://www.google.com.


To add headers to a Request please visit Adding HTTP Headers To Requests in Filters and Servlets.

Create Your Own Pure Javascript Widgets

Why use other peoples widgets and mashups when you can build your own? Forget the sites that offer free widgets and create your own instead. Build widgets that are vendor agnostic and can be embedded in any webpage or blog. It's not hard once you understand the basics of web 2 and some javascript. Here are the advantages of pure javascript widgets...
  • Pure javascript widgets, no perl or php backends required.
  • Use of free APIs from Google, Yahoo, Twitter etc. No need to pay for anything
  • Place these widgets on any website or blog? Blogger, Wordpress etc.
  • Make your website funky and sexy, and all for FREE
  • Learn javascript


Widgets
Funky Twitter Thoughts widgets that displays whats on your mind. Customize it to anyone on twitter- including Paris Hilton.
View this widget





Mash up using PHP cURL, JSON and javascript to show where you are surfing from.
View this Widget







Weather widget that shows the weather in a region in a country. Customize this to which ever country and regions you like. Or even the capital cities around the world.
View this Widget






Advanced topics
Practical Javascript Multithreading Using iFrames

Funky Twitter Thoughts Widgets - Using Multiple API Calls

Description

This is a pure javascript widget. This widget displays a keyword map of the various kewwords in a twitter user's statuses. The keywords are highlighted by their frequency. The widget uses IFRAME based multi-threading to keep the reponse times down as it makes over 100 Yahoo API calls to the yahoo context API for keyword extraction.

View the Widget



APIs Used
Yahoo Context API
Twitter user timeline API

How It Works
First, the code makes a call to the twitter api for a particular user and gets the first 100 statuses by that user. Next, it makes a call to the yahu context api for each of those statuses (100 calls). After the keywords are extracted it keeps a count of how many times a word is mentioned. The more it's mentioned the bolder the text.

This example uses a form of faux multi-threading using iframes. This is to reduce the amount of time taken to make the 100 api calls. For a tutorial on this multi-threading methodology please see Real Javascript multithreading using iframes

You can download the zipped example here.

This example is completely self contained and should run from your desktop without any issues. In IE you will get a "warning", and you will have to allow blocked content. This is only because you are running it off the desktop.

For completeness, the code is given below.
 1. Yahu_appid="sQV.btjV34GS4QX9sJM5h45PV_suKMOJPEcn3pYRbdgHG840E3wMIrhqbDRrsg";
 2. 
 3. var twittercurrentkeyval;
 4. var twittercurrentalloc;
 5. var twitterthreadlimit;
 6. var Twt_twitterthreadsrunning=0;
 7. 
 8. function Twt_twitterresultclass(){}
 9. var Twt_twitterresults = new Array();
10. var Twt_twitterkeywords = new Array();
11. 
12. var Twt_twitterresultslength=0;
13. var Twt_twitterresultspage=0;
14. var Twt_twitterresultscountonpage=0;
15. var Twt_twittercurrentcount=0;
16. 
17. var twitterreulstset;
18. 
19. var twitterstarttime;
20. 
21. function Twitter_CallUserSearch(user, context, noofthreads){
22.     if(context==null && user==null){
23.         return;
24.     }
25.     else if(user!=null){
26.         twitterstarttime = new Date().getTime();
27.         twitterthreadlimit=(noofthreads==null?10:noofthreads);
28.         for(i=0;i<twitterthreadlimit;i++)
29.             document.write("<iframe id=\"twitterload"+i+"\" style=\"width:0px;height:0px;border:none\"></iframe>");
30. 
31.         document.write("<script type=\"text/javascript\" src=\"http://twitter.com/statuses/user_timeline.json?user_id="+user+"&"+
32.                     "callback=Twitter_ShowResults&count=50\"/>");
33.     }
34.     else{
35.         document.write("<script type=\"text/javascript\" src=\"http://search.yahooapis.com/ContentAnalysisService/V1/termExtraction?"+
36.             "appid="+Yahu_appid+
37.             "&context="+context+
38.             "&output=json"+
39.             "&query="+"celebrity"+
40.             "&callback=parent.Yahu_ContextCallback\"/>");
41.     }
42. 
43. }
44. 
45. function Twitter_RemoveBadChars(s){
46.     s = s.replace(/[^a-zA-Z0-9]/g, " "); 
47.     s = s.replace(/ /g,"+");
48.     return s;    
49. }
50. 
51. function Twitter_ShowResults(rsp){
52.     twitterreulstset=rsp;
53.     Twt_twitterresultslength=rsp.length;
54.     for (i=0;i<rsp.length;i++){
55.         var rsi=rsp[i];
56.         tmpcls = new Twt_twitterresultclass();
57.         tmpcls.text = rsi.text;
58.         tmpcls.date = rsi.created_at;
59.         Twt_twitterresults.push(tmpcls);
60.     }
61.     Twt_CallThreads();
62.                 
63. }
64. var twitterpercentcomplete="0";
65. function Twt_CallThreads(){
66.     var i;
67.     var x = Twt_twitterresultspage*twitterthreadlimit;
68.     twitterpercentcomplete="<h2>"+Math.round(x*100/Twt_twitterresultslength) +" %  please wait</h2>";
69.     if((Twt_twitterresultslength-x)<=0){
70.         Twt_Finished();
71.         return;
72.     }
73.     for(i=0 ; i<twitterthreadlimit && i < (Twt_twitterresultslength - x) ; i++){
74.         tmps = MyGetThisPage()+"?context="+escape(Twitter_RemoveBadChars(Twt_twitterresults[x+i].text));
75.         document.getElementById("twitterload"+i).src=tmps;
76.     }
77.     Twt_twitterresultscountonpage=i;
78. }
79. 
80. function Twt_ThreadCallback(){}
81. 
82. var twitterinterimresult;
83. function Yahu_ContextCallback(rsp){
84.     twitterinterimresult="";
85.     var wordcount;
86.     for(i=0;i<rsp.ResultSet.Result.length;i++){
87.         keyword = rsp.ResultSet.Result[i]
88.         twitterinterimresult+=keyword+" ";
89.         if(Twt_twitterkeywords[keyword]==null){
90.             wordcount=1;
91.             for(oldkeyword in Twt_twitterkeywords){
92.                 if( oldkeyword.indexOf(keyword)>=0 )
93.                     wordcount++;
94.                 else if (keyword.indexOf(oldkeyword)>=0)
95.                     Twt_twitterkeywords[oldkeyword]++;
96.                 else{}    
97.             }
98.             Twt_twitterkeywords[keyword]=wordcount;
99.         }
100.         else
101.             Twt_twitterkeywords[keyword]++;           
102.     }
103.     document.getElementById("twitterresult").innerHTML=twitterpercentcomplete+"  "+twitterinterimresult;
104.     
105.     if(--Twt_twitterresultscountonpage == 0){
106.       Twt_twitterresultspage++;
107.       Twt_CallThreads();
108.     }              
109. }
110. 
111. function Twt_Finished(){
112.     var size;
113.     var text="";
114.     var basesize=11;
115.     for(keyword in Twt_twitterkeywords){
116.         size = Twt_twitterkeywords[keyword]>7?7:Twt_twitterkeywords[keyword];
117.         if(Twt_twitterkeywords[keyword]>1)
118.             text+="<span style=\"font-size:"+(basesize+size*3)+"px\"><b>"+keyword+"</b></span>";
119.         else
120.             text+="<span style=\"font-size:"+basesize+"\">"+keyword+"</span>";
121.         text+="  ";    
122.     }
123.     text+="<br/><br/><span style=\"font-size:"+basesize+"\">("+twitterthreadlimit+" threads, "+(new Date().getTime()-twitterstarttime)+" ms)</span>";
124.     document.getElementById("twitterresult").innerHTML=text;
125. }
126. 
Hide line numbers

Real Javascript Multithreading Using iFrames

Aim
The aim of this javascript example is to demonstrate how you can achieve a form of real, practical and valuable Javascript Multi-threading using IFRAMEs. We will also have a look at a graph showing the speed increase you can get using a real life widget that uses this kind of multi-threading methodology. This is not about simulating multi-threading using javascript timeouts or some theoretical asynchronous bit of code.

Assumptions
This assumes that you have a little javascript knowledge. Beginner level is fine to understand the principle behind iframe based multi-threading. You don't need any prior knowledge to analyse the response times of the realworld example.

This article is broken into the 5 sections shown below. They are all on the same page.

Concept

A schematic of the code is show below. The basic idea is that a parent will load html/javascript into it's iframes. These html/javascript code will then run in the iframes and write the results back to the parent using parent.functionName. This way we can simulate multi-threading. This is very similar to how the linux fork works. There is an amazing performance advantage which we will see later on. This code is available at the end of this page (in the appendix) if you wish to save it on to your PC and try it out.



1. The html file loads for the first time. This is the parent as threadid==null.

2. It loads a copy of itself into each of the 5 IFRAMEs, with a url parameter x=1, x=2... for each of the IFRAMEs. These become children.

3. The children in the IFRAMEs do some work.

4. The child calls parent.ThreadCallback in the parent. Each of the children call this function when they have finished.



This is very similar to fork method in linux. We use an id passes through the url to identify what thread it is. This also allows us to identify the parent from the children.


Graphs and Discussion

Let us have a look at the graph generated using javascript iframe multi-threading. The widget used to create this graph, calls the twitter api to get approximately 100 statuses from a user and then makes a Yahoo context API call for each of those 100 statuses to extract the keywords. The number of threads in the graph represent the number of IFRAMEs used.

If you observe the graphs for firefox, you can see that as the threads increase, the total time to make all the API calls decreas up to a point, and then it doesn't decrease further. This is consistent with the behaviour of response times in multi-threaded environments and is the law of diminishing returns.

If you look at the vanilla IE (pink) graph, you will notice that after 2 threads the results are more or less constant regardless of the number of threads. This is because IE limits the number of simultaeneous connections to 2. Therefor having more IFRAMEs is not reducing the total response times.

The IE MaxConnectionsPerSever-64 Graph has the registry hack that sets the maximun number of concurrent connections in IE to 64. Now you can see that the total response times reduce dramatically as you increase the number of IFRAMEs, upto a certain point. After this point, increasing the IFRAMEs is not showing any benefit. You would have also noticed that the response times for both IE graphs are almost exact for 1 and 2 threads. This is as it should be, because both are the same IE.


Conclusion

The graph shows conclusively that using multiple IFRAMEs -for javascript code that uses repeated http or ajax calls to services- can dramatically cut down on your response times. This also show that IFRAME base multi-threading is not some theoretical artifact but is solid code that can be put into practice to yield tangiable results.


Example

Here is the real world example. This is a pure javascript widget that displays the extracted keywords from a twitter user's statuses. You will definitely notice a distinct difference between the two.

Lauch the widget using 2 threads
Lauch the widget using 5 threads
Launch the widget using 10 threads
Launch the widget using 15 threads

Please note that for the graphs in the previous section, a stripped down version of the widget was used, which was not embedded in a blog.

For more details on the widget and to download the source code please visit Funky Twitter Thoughts Widget


Appendix
The code discussed in the "concept"
 1. <html>
 2. <head>
 3. <script>
 4. /*Dont worry about this. This is just ot get the url parameters only*/
 5. function MyGetUrlParams(){
 6.   var url_params = new Array();
 7.   var urla = location.href.substring(location.href.indexOf('?')+1).split('&');
 8.   for(i=0;i< urla.length ;i++){
 9.     url_params[urla[i].substring(0,urla[i].indexOf('='))]=
10.     urla[i].substring(urla[i].indexOf('=')+1);
11.   }
12.   return url_params;
13. }
14. 
15. /*This is the callback that gets called when a thread finishes*/
16. function ThreadCallback(tid, message){
17.   alert(tid+":"+message);
18. }
19. 
20. /*This is a parameter that identifies a thread*/
21. threadid = MyGetUrlParams()["x"];
22. 
23. </script>
24. </head>
25. <body>
26. Multi-threading test <br/>
27. <iframe style="width:50px;height:50px" id='div0'></iframe>
28. <iframe style="width:50px;height:50px" id='div1'></iframe>
29. <iframe style="width:50px;height:50px" id='div2'></iframe>
30. <iframe style="width:50px;height:50px" id='div3'></iframe>
31. <iframe style="width:50px;height:50px" id='div4'></iframe>
32. 
33. <script>
34.   if(threadid==null){
35.     /* Parent */
36.     for(i=0;i<5;i++){
37.       document.getElementById("div"+i).src="jsmultithreading.html?x="+i ;
38.     }
39.   }
40.   else{
41.     /* do some work and return a message*/
42.     parent.ThreadCallback(threadid, "Phew! I have finished working");
43.   }
44. </script>
45. </body>
46. </html>
Hide line numbers

Whats on Kim Kardashian's Mind? Twitterthoughts Widget

Find out what's been on Kim Kardashians twitter mind in the past week.
Learn more about this widget
A twiter widget that displays what has been on Kim Kardashian's mind for the past week. This widget can be easily adapted to display any celebrity or entity on Twittter. Pure Javascript only. Using Twitter and Yahoo APIs

Find Code Diaries On the Web

There are many sites which refer back to TidyTutorials formerly Code Diaries. Find out what these are here. As tidyTutorials ( Code Diaries ) increase in popularity, so do the links to it. Thank you everyone for amking this site a success.

Code Diaries on RollYo

Code Diaries on Alexa

Code Diaries on Who is

Aboutus.org's information on Code Diaries

Code on Rediff and Code's Rediff Blog

Code Diaries on robotex

Windows C++ Socket Example Using Client Server and Multi-Threading

Aim
The aim of this C++ tutorial is to demonstrate simple client/server socket communication and multi-threading on Windows. This demonstrates basics such as binding, listening and accepting sockets for Servers and connecting sockets for clients. Once the server accepts a socket, a thread is spawned to handle it. This is the simplest Windows C++ socket (blocking) example you can find. Please leave any comments or questions at the end of this tutorial and I will endeavour to answer them.

Assumptions
This article assumes that you have VC++ installed and configured. See Problems and Solutions Installing VC++ Express Edition, to install and run vcvars32.bat.

Versions used in this example
Sofware/ComponentImage
Windows XP SP2N/A
Visual Studio Express Editions 2008 VC++N/A
Links to these files can be found here

You can download the zipped example here.

Steps required for a server socket
  1. Use WSAStartup() to initialize socket support. You only need this for VC++
  2. Initialize the socket using socket().
  3. Set any options such as blocking etc using setsockop().
  4. Bind to the local address and port using bind(). For a server use INADDR_ANY as the address.
  5. listen() for connections.
  6. Go into a loop and accept connections usin accept(). Spawn threads to handle these connections, so you can accept more connections.
    • Read and write to the socket. within the thread.
    • closesocket()
      • When you are done, close the server socket using closesocket()

      Steps required for a client socket
      1. Use WSAStartup() to initialize socket support. You only need this for VC++
      2. Initialize the socket using socket().
      3. Set any options such as blocking etc using setsockop().
      4. Connect to the remote host using connet(). Supply address and port here.
      5. Read and write to the socket. closesocket()

      Write and compile the Server
      1. The server listens for a connection. When it receives a connection it spawns a tread to handle it. This thread then reads from the socket, appends " SERVER ECHO" to it and sends it back to the client. As the server doesn't require an IP address, we assign INADDR_ANY to the sockaddr_in struct. Save this code as WinSever.cpp.
         1. #include <winsock2.h>
         2. #include <windows.h>
         3. #include <fcntl.h>
         4. #include <string.h>
         5. #include <stdlib.h>
         6. #include <errno.h>
         7. #include <stdio.h>
         8. 
         9. DWORD WINAPI SocketHandler(void*);
        10. 
        11. int main(int argv, char** argc){
        12. 
        13.     //The port you want the server to listen on
        14.     int host_port= 1101;
        15. 
        16.     //Initialize socket support WINDOWS ONLY!
        17.     unsigned short wVersionRequested;
        18.     WSADATA wsaData;
        19.     int err;
        20.     wVersionRequested = MAKEWORD( 2, 2 );
        21.      err = WSAStartup( wVersionRequested, &wsaData );
        22.     if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
        23.             HIBYTE( wsaData.wVersion ) != 2 )) {
        24.         fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
        25.         goto FINISH;
        26.     }
        27. 
        28.     //Initialize sockets and set any options
        29.     int hsock;
        30.     int * p_int ;
        31.     hsock = socket(AF_INET, SOCK_STREAM, 0);
        32.     if(hsock == -1){
        33.         printf("Error initializing socket %d\n",WSAGetLastError());
        34.         goto FINISH;
        35.     }
        36.     
        37.     p_int = (int*)malloc(sizeof(int));
        38.     *p_int = 1;
        39.     if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
        40.         (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
        41.         printf("Error setting options %d\n", WSAGetLastError());
        42.         free(p_int);
        43.         goto FINISH;
        44.     }
        45.     free(p_int);
        46. 
        47.     //Bind and listen
        48.     struct sockaddr_in my_addr;
        49. 
        50.     my_addr.sin_family = AF_INET ;
        51.     my_addr.sin_port = htons(host_port);
        52.     
        53.     memset(&(my_addr.sin_zero), 0, 8);
        54.     my_addr.sin_addr.s_addr = INADDR_ANY ;
        55.     
        56.     if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
        57.         fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
        58.         goto FINISH;
        59.     }
        60.     if(listen( hsock, 10) == -1 ){
        61.         fprintf(stderr, "Error listening %d\n",WSAGetLastError());
        62.         goto FINISH;
        63.     }
        64.     
        65.     //Now lets to the server stuff
        66. 
        67.     int* csock;
        68.     sockaddr_in sadr;
        69.     int    addr_size = sizeof(SOCKADDR);
        70.     
        71.     while(true){
        72.         printf("waiting for a connection\n");
        73.         csock = (int*)malloc(sizeof(int));
        74.         
        75.         if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
        76.             printf("Received connection from %s",inet_ntoa(sadr.sin_addr));
        77.             CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
        78.         }
        79.         else{
        80.             fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
        81.         }
        82.     }
        83. 
        84. FINISH:
        85. ;
        86. }
        87. 
        88. DWORD WINAPI SocketHandler(void* lp){
        89.     int *csock = (int*)lp;
        90. 
        91.     char buffer[1024];
        92.     int buffer_len = 1024;
        93.     int bytecount;
        94. 
        95.     memset(buffer, 0, buffer_len);
        96.     if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
        97.         fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
        98.         goto FINISH;
        99.     }
        100.     printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
        101.     strcat(buffer, " SERVER ECHO");
        102. 
        103.     if((bytecount = send(*csock, buffer, strlen(buffer), 0))==SOCKET_ERROR){
        104.         fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
        105.         goto FINISH;
        106.     }
        107.     
        108.     printf("Sent bytes %d\n", bytecount);
        109. 
        110. 
        111. FINISH:
        112.     free(csock);
        113.     return 0;
        114. }
        Hide line numbers
      2. Open a prompt to the working directory and compile the code using the windows cl.exe compiler. You just need to include the ws2_2.lib.

        ..workspace\SocketExample>cl WinServer.cpp ws2_32.lib.lib

      Write and compile the Client
      1. The client reads a line from the console and sends this to the server. It then reads from the server and displays it on the console. Save this code as WinClient.cpp.
         1. #include <winsock2.h>
         2. #include <windows.h>
         3. #include <fcntl.h>
         4. #include <string.h>
         5. #include <stdlib.h>
         6. #include <errno.h>
         7. #include <stdio.h>
         8. #include <conio.h>
         9. 
        10. int main(int argv, char** argc){
        11. 
        12.     //The port and address you want to connect to
        13.     int host_port= 1101;
        14.     char* host_name="127.0.0.1";
        15. 
        16.     //Initialize socket support WINDOWS ONLY!
        17.     unsigned short wVersionRequested;
        18.     WSADATA wsaData;
        19.     int err;
        20.     wVersionRequested = MAKEWORD( 2, 2 );
        21.      err = WSAStartup( wVersionRequested, &wsaData );
        22.     if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
        23.             HIBYTE( wsaData.wVersion ) != 2 )) {
        24.         fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
        25.         goto FINISH;
        26.     }
        27. 
        28.     //Initialize sockets and set any options
        29.     int hsock;
        30.     int * p_int ;
        31.     hsock = socket(AF_INET, SOCK_STREAM, 0);
        32.     if(hsock == -1){
        33.         printf("Error initializing socket %d\n",WSAGetLastError());
        34.         goto FINISH;
        35.     }
        36.     
        37.     p_int = (int*)malloc(sizeof(int));
        38.     *p_int = 1;
        39.     if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
        40.         (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
        41.         printf("Error setting options %d\n", WSAGetLastError());
        42.         free(p_int);
        43.         goto FINISH;
        44.     }
        45.     free(p_int);
        46. 
        47.     //Connect to the server
        48.     struct sockaddr_in my_addr;
        49. 
        50.     my_addr.sin_family = AF_INET ;
        51.     my_addr.sin_port = htons(host_port);
        52.     
        53.     memset(&(my_addr.sin_zero), 0, 8);
        54.     my_addr.sin_addr.s_addr = inet_addr(host_name);
        55. 
        56. 
        57.     if( connect( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == SOCKET_ERROR ){
        58.         fprintf(stderr, "Error connecting socket %d\n", WSAGetLastError());
        59.         goto FINISH;
        60.     }
        61. 
        62.     //Now lets do the client related stuff
        63. 
        64.     char buffer[1024];
        65.     int buffer_len = 1024;
        66.     int bytecount;
        67.     
        68.     int c;
        69.     memset(buffer, '\0', buffer_len);
        70. 
        71.     for(char* p=buffer ; (c=getch())!=13 ; p++){
        72.         printf("%c", c);
        73.         *p = c;
        74.     }
        75.     
        76.     if( (bytecount=send(hsock, buffer, strlen(buffer),0))==SOCKET_ERROR){
        77.         fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
        78.         goto FINISH;
        79.     }
        80.     printf("Sent bytes %d\n", bytecount);
        81. 
        82.     if((bytecount = recv(hsock, buffer, buffer_len, 0))==SOCKET_ERROR){
        83.         fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
        84.         goto FINISH;
        85.     }
        86.     printf("Recieved bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
        87. 
        88.     closesocket(hsock);
        89.     
        90. FINISH:
        91. ;
        92. }
        Hide line numbers

      2. Open a prompt to the working directory and compile the code using the windows cl.exe compiler. You just need to include the ws2_2.lib.

        ..workspace\SocketExample>cl WinClient.cpp ws2_32.lib.lib


      Run the example
      1. Open a prompt to the working directory and run the server.

        ..workspace\SocketExample>WinServer.exe

      2. Open another prompt to the working directory and run the Client.

        ..workspace\SocketExample>WinClient.exe

      3. Now type something into the client prompt and press ENTER.
      4. You will see the exchange between client and server. You can open many client prompts at the same time and test.

      Enumerating, Deleting and Creating Registry Entries in Windows C++

      Aim
      The aim of this example is to demonstrate programatic registry manipulation in C++ on Windows. This will use functions such as RegCreateKey, RegSetValueEx and RegDeleteValue. Leave any questions or problems as comments and I will endeavour to answer them.

      Assumptions
      This article assumes that you have VC++ installed and configured. See Problems and Solutions Installing VC++ Express Edition, to install and run vcvars32.bat.

      Versions used in this example
      Sofware/Component
      Image
      Windows XP SP2
      N/A
      Visual Studio Express Editions 2008 VC++
      N/A
      Links to these files can be found here

      You can use either regedit or regedt32 to view the results.

      Write and compile the application
      1. This example will display the registry under SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run. It will then add and delete registry values. Save the code below as registryhack.cpp.
         1. #include <windows.h>
         2. #include <iostream>
         3. 
         4. using namespace std;
         5. 
         6. void ShowCurrentVersionRun();
         7. void ModifyCurrentVersionRun(int);
         8. 
         9. void main(char** argc, int argv){
        10. 
        11.     ModifyCurrentVersionRun(1);    //add a key
        12.     ShowCurrentVersionRun();
        13.     cout<<"----------------------------------------"<<endl;
        14.     ModifyCurrentVersionRun(0);    //remove the key
        15.     ShowCurrentVersionRun();
        16. }
        17. 
        18. void ShowCurrentVersionRun(){
        19.     HKEY hKey;
        20. 
        21.     if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 
        22.                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
        23.                 0, NULL, 0, KEY_ALL_ACCESS, NULL,
        24.                 &hKey, NULL) == ERROR_SUCCESS) {
        25.     
        26.         TCHAR rval[256];
        27.         DWORD  rval_len = 256 ;
        28.         
        29.         unsigned char rdata[256];
        30.         DWORD rdata_len = 256;
        31.         
        32.         DWORD rtype = REG_SZ ;
        33.         int i = 0;
        34.         
        35.         while( RegEnumValue(hKey, i, rval, &rval_len, NULL, &rtype, 
        36.                 rdata, &rdata_len) != ERROR_NO_MORE_ITEMS){
        37.                 
        38.             cout<<rval<<" : "<<rdata<<endl;
        39.             i++;
        40.             rval_len=256;
        41.             rdata_len=256;
        42.             memset(rval, '\0', rval_len);
        43.             memset(rdata, '\0', rdata_len);
        44.         }
        45.         RegCloseKey (hKey);    
        46.     }
        47. }
        48. 
        49. void ModifyCurrentVersionRun(int install){
        50.     HKEY hKey;
        51.     if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 
        52.                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
        53.                 0, NULL, 0, KEY_ALL_ACCESS, NULL,
        54.                 &hKey, NULL) == ERROR_SUCCESS) {
        55. 
        56.         TCHAR* rval = "My Dummy Key";
        57.         TCHAR* rdata = "************* My Dummy Data ************* ";
        58.         if(install)
        59.             RegSetValueEx (hKey, rval, 0, REG_SZ, (PBYTE)rdata,    strlen(rdata));
        60.         else
        61.             RegDeleteValue(hKey, rval);
        62.         RegCloseKey (hKey);    
        63.     }
        64. }
        Hide line numbers

      2. Open a prompt to the working directory and compile the code using the windows cl.exe compiler. You just need to include the advapi32.lib.

        ..workspace\RegistryHack>cl registryhack.cpp advapi32.lib

      3. Now run the program in the command prompt. You will see two emumerations. The fisrt one has the "dummy" entry added and in the second one it is removed. You can modify the code and check the results using regedit or regedt32