Profile

Click to view full profile
Hi, I'm Veerapat Sriarunrungrueang, an expert in technology field, especially full stack web development and performance testing.This is my coding diary. I usually develop and keep code snippets or some tricks, and update to this diary when I have time. Nowadays, I've been giving counsel to many well-known firms in Thailand.
view more...

Sunday, January 27, 2013

Image POST Client and Sever in Python and C#

From last time, I had told how to encode image into base64 string[1], and how to do POST message to HTTP server[2][3] This post will continue from those posts. First, we will create HTTP POST server in Python. I based on the concept that a message will be encoded using url-encode format in a form of base64 string, and the image string will be sent to a variable named "img". It will decode an image string from that variable.
import SimpleHTTPServer
import SocketServer
import cgi
from base64 import decodestring

PORT = 8000

class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):

 def _writeheaders(self):
  self.send_response(200)
  self.send_header('Content-type', 'text/html')
  self.end_headers()

 def do_GET(self):
  filename = 'temp.png'
  f = open(filename, 'rb')
  encode = f.read().encode('base64')
  img = '<img height="200" src="data:image/png;base64,' + encode + '" width="250" />'
  self._writeheaders()
  self.wfile.write("""
  <html><head><title>Simple Server</title></head>
   <body>
    It worked!!!!
 
    %s
   </body>
  </html>"""  % (img))
 def do_POST(self):
  form = cgi.FieldStorage(
   fp=self.rfile,
   headers=self.headers,
   environ={'REQUEST_METHOD':'POST',
      'CONTENT_TYPE':self.headers['Content-Type'],
     })
  encode = form['img'].value
  decode = decodestring(encode)
  output = open('temp.png', 'wb')
  output.write(decode)
  output.close()
  # After posting image has done, it will response GET message to show that image
  self.do_GET()

Handler = ServerHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()
Then, we will create HTTP POST client to upload an image to our HTTP POST server.
Python:
import urllib, urllib2

uri = 'http://localhost:8000'
filename = 'Leafa.jpg'
f = open(filename, 'rb')
encode = f.read().encode('base64')
params = { 'img' : encode }
data = urllib.urlencode(params)

p = urllib2.urlopen(uri, data)
print p.read()
C# WPF:
string fileName = "Leafa.jpg";
StreamResourceInfo sri = null;
Uri uri = new Uri(fileName, UriKind.Relative);
sri = Application.GetResourceStream(uri);

using (var memoryStream = new MemoryStream())
{
    sri.Stream.CopyTo(memoryStream);
    byte[] result = memoryStream.ToArray();
    var base64 = "img=" + HttpUtility.UrlEncode(System.Convert.ToBase64String(result));

    MessageBox.Show(base64);

    using (var wc = new WebClient())
    {
        wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
        wc.UploadStringCompleted += wc_UploadStringCompleted;
        wc.UploadStringAsync(new Uri(url), "POST", base64);
    }
}
The server will response a web page, which the client will show that response as a text format, so, if you want to make sure that your image are already uploaded, just check it the "server.py" directory. You will see the image named "temp.png", which is converted from jpg image in the client side. Moreover, you can use a web browser request to http://localhost:8000 to let GET response show you that uploaded one.

The sample project is uploaded, can download from http://www.mediafire.com/?1okv3lc6nk1jsc7.

Leafa.jpg
References:
  1. Encode an Image into base64 string in C# / Python
  2. Simple HTTP POST Server / Client with Python
  3. HTTP POST data via WebClient and WebRequest

STA and MTA

This post is written because when I wrote the multithreads application, mostly in UI contained apps, it will ask for using STA in some methods. Then, I really curious what it is and find out why need to use STA, and how about MTA. In short, STA and MTA indicates where the thread resources will be located. If some objects need like COM objects, they are not thread safe which don't handle thread synchronization, commonly used in UI compoment. To call COM objects in other threads, they need to marshal message to the STA thread using message pumping system.

References:

Friday, January 25, 2013

Windows Azure Errors Guide

If you face provisioning timed out during restore virtual machine from image file: Azure (IaaS) Provisioning Timed Out.

If you face the provisioning operation is too long, look at "The operation cannot be performed because the virtual machine is faulted."

P.S. If I find anymore unexpected errors, I will update to this post.

Saturday, January 19, 2013

Useful Links for XNA Novice Startup

This link will guide from the loading resource files to animating multiple sprite objects: http://www.xnadevelopment.com/tutorials.shtml

This link will give a set of sample walkthrough projects to let us follow: http://www.riemers.net/

Tuesday, January 15, 2013

Double NAT - How to solve it?

Before I going to explain how to solve double NAT problem, I will introduce what is NAT first. Due to the number of IP addresses on internet is limited, NAT (Network Address Translation) was introduced. A router will use only one public IP address (Gateway), however, a network behind NAT is using private IP addresses, which is valid within the router network. To be able to access a network within NAT, port forwarding is required in order to bypass the public IP address with a specific port to a specific private IP address with specific port as well. This scenario represents a single level of NAT, having only one router cover all the entire network. But it often isn't simple like this.

Double NAT is a scenario where multiple routers on network do network address translation. The most common sample is a Cable or DSL modem is connected to a Wi-Fi router. NAT of both modem and router are enabled. Then, computers on the network are connected to the Wi-Fi router. In this scenario, even if port forwarding is setup on the Wi-Fi router, the computer will not be accessible from internet because the Wi-Fi doesn't have a public IP address. It has only a private IP address, which is given from the Cable/DSL modem. There are many solutions to solve this problem, however, there is no silver bullet. It depends on situation which one is suitable.

Possible Solutions: 

1. Setup PPPoE connection between the wireless router and modem 

This is the most robust solution, unfortunately not all ISPs provide enough information for this to be setup easily 

PPPoE can be usually setup in the wireless router's WAN settings. There are usually multiple options to configure the WAN connection of wireless router, amongst which are DHCP and PPPoE. DHCP is no good here, as it results in private IP address assigned to the WiFi router. PPPoE is better, because it bypasses the NAT in the modem, however it might need login and password information which the ISP might not provide.

2. Put the wireless router in bridged mode 

Bridged mode on wireless router means that NAT and DHCP functions on it will be disabled. Some router call it bridged mode, some simply allow you to disable NAT and DHCP. Unfortunately some WiFi routers simply don't support bridged mode at all. 

If you manage to switch router to bridged mode, all port forwarding needs to be configured on the modem (either automatically if it supports NAT-PMP, or manually).

3. Put the wireless router in modem's DMZ 

DMZ (demilitarized zone) is a common feature of router that allow to chose one client to which all traffic is forwarded. If your modem supports DMZ, this might be solution for you: 

1. Find out the WAN address of wireless router. For this you might need to log in to the WiFi router admin interface and look at the Status page (most router's have status pages which show relevant information about the WAN connection). 

2. Log in to the modem web administration interface, find the DMZ settings and put the WiFi router's IP WAN address there. 

Note that with this solution you will still get a double NAT warning in Air Video Server, but if the port forwarding on Wireless router is setup correctly, things should work.

4. Forward the port 45631/TCP in the modem to the router

This solution is similar to [3], except that instead of putting the WiFi router to modem's DMZ only one port is forwarded. 

1. Find out the WAN address of wireless router. For this you might need to log in to the WiFi router admin interface and look at the Status page (most router's have status pages which show relevant information about the WAN connection). 

2. Login in the modem web admin interface and configure port forwarding of port 45631 (protocol TCP) to the address from router's status page.

Note that with this solution you will still get a double NAT warning in Air Video Server.

From mentioned solutions, for me, I prefer to use the first two solutions because they are easy to setup, just setting either a DSL/Cable modem or Wi-Fi router to a bridged mode. The  two nested networks will become one. It is different only in setting DSL/Cable modem or router to a bridged mode is needed to use a Wi-Fi router connecting to ISP using PPPoE with username and password, but setting a Wi-Fi router to a bridged mode, the DSL/Cable modem or router must be able to set port forwarding, which in some routers there is only one direction from in to out, doesn't allow outside network coming in.

Reference: http://inmethod.com/forum/posts/list/908.page -> This thread helps me so much, thanks to him.

Thursday, January 3, 2013

Encode an Image into base64 string in C# / Python

From previous post is about display an embed string image into HTML. So, this post is about how to get base64 string image both Python and C#.

I will start from Python which we can convert into base64 string easily using encode function.
filename = 'xxx.jpg'
f = open(filename, 'rb')
encode = f.read().encode('base64')
print encode
If you want to decode it back into original string and write it into an image file, we can do as follows:
from base64 import decodestring

decode = decodestring(encode)
print decode

output = open('temp.png', 'wb')
output.write(decode)
output.close()
From the example, the result is it will convert a jpeg image into a png image. Use "decodestring" function that imported from "base64" module.

In C# (WPF, SL, WP), we can convert it by getting resource stream then copy to memory stream array, and convert it into base64 string.
public void Convert()
{
     string filename = "xxx.jpg";
     StreamResourceInfo sri = null;
     Uri uri = new Uri(fileName, UriKind.Relative);
     sri = Application.GetResourceStream(uri);

     using (var memoryStream = new MemoryStream())
     {
          sri.Stream.CopyTo(memoryStream);
          byte[] result = memoryStream.ToArray();
          string base64 = System.Convert.ToBase64String(result);
     }
}
For both Python and C# from my code, if you want to send the data upload to the web server using HTTP POST method, you need to do another step by encoding into the same form format in the sever side such as url-encode. You can take a look in my old posts to send data using HTTP POST for Python and C#.

References:

Embedding string base64 image into HTML

Sometimes when we have to deal with dynamic images in web application, we can't just use the link refer to any image because we just want to generate it for temporary purpose. In order to solve this problem, HTML is be able to read an image data in form of base64 string then show an image in the browser.

It's a simple to express an image in string format using the following template:
<img src="data:image/[format];base64,[base64 image string]"/>
Example:
<img src="data:image/png;base64,iVBORw0KGgoAAAANS..."/>
In the next post, I will write about how to get base64 string from an image.

Reference: Embedding Base64 Image Data into a Webpage

Wednesday, January 2, 2013

Happy New Year 2013 :)

Happy New Year 2013, this is the 3rd anniversary of this blog. I will try to write more useful posts, and more specific topics, not just beginner topics ^^. Finally, wishes you all happy and healthy all the year and enjoy life :)