I have the follow class, extending Thread.
The idea is to extract the date inside the thread, and everything goes well, until the sometime when the received data is larger than a few kilobytes, and then i am starting to reading complete incorrect data.
public class ThreadBooksPositions extends Thread
{
public ThreadBooksPositions()
{
}
..
// default constructors
public void run()
{
InputStream iSS = null;
HttpURLConnection connection = null;
Integer sectionsDescriptorSize1 = 0;
Integer sectionsDescriptorSize2 = 0;
try
{
URL url = new URL( "192.168.1.4/bookstore.asp?getbooks" );
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod( "GET" );
connection.connect();
iSS = connection.getInputStream();
BufferedInputStream bIS = new BufferedInputStream( iSS );
if( bIS.available() > 4 )
{
Float lat = 0F;
Float lng = 0F;
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bf;
try
{
bf = new byte[ bIS.available() ];
while ( bIS.read( bf ) != -1)
out.write( bf ); //copy streams
out.flush();
}
catch ( IOException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
} //you can configure the buffer size
byte[] bO = out.toByteArray();
if( out != null )
{
try
{
out.close();
}
catch ( IOException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ByteBuffer data = ByteBuffer.wrap( bO );
sectionsDescriptorSize1 = data.getInt();
sectionsDescriptorSize2 = data.getInt();
ByteBuffer sectionData;
try
{
if( sectionsDescriptorSize1 > 0 )
{
byte[] bAS0 = new byte[ sectionsDescriptorSize1 ];
data.get( bAS0 );
}
if( sectionsDescriptorSize2 > 1 )
{
// trajectory
byte[] bAS1 = new byte[ sectionsDescriptorSize2 ];
data.get( bAS1, 0, sectionsDescriptorSize2 );
sectionData = ByteBuffer.wrap( bAS1 );
Boolean readingFailed = true;
if( sectionData != null )
{
while( sectionData.available() > 1 )
{
try
{
readingFailed = false;
lat = sectionData.getFloat(); // 4
lng = sectionData.getFloat(); // 4
}
catch( Exception e )
{
readingFailed = true;
}
try
{
if( readingFailed == false )
{
addBookStorePosition( lat, lng );
}
}
catch (Exception e)
{
}
}
}
}
catch( Error e )
{
}
}
}
catch( IOException e )
{
}
finally
{
if( iSS != null )
{
try
{
iSS.close();
}
catch( IOException e )
{
}
}
if( connection != null )
{
connection.disconnect();
}
}
}
}
What might cause reading of incorrect data ?
Found the issue.
Seems like .available() is causing the issue, especially in a threads.
Related
I am using UART to get the input to my system from PIC Development Board. and I use the following code to get the values from the board.
public SerialReader( InputStream in ) {
this.in = in;
}
public void run() {
byte[] buffer = new byte[ 1024 ];
int len = -1;
try {
/*len = this.in.read(buffer);
int x = buffer[0] & 0xff;
System.out.println(buffer[0]);
System.out.println(x);
System.out.println((char)x);*/
while( ( len = this.in.read( buffer ) ) > -1 ) {
System.out.print( new String( buffer, 0, len ) );
System.out.println(len);
/*String s = new String(buffer); //buffer.toString(); 1
System.out.println(s);
for (int i=0; i<=buffer.length; i++)
System.out.println(buffer[i]);
//System.out.print( new String( buffer, 0, len ) );
*/ }
} catch( IOException e ) {
e.printStackTrace();
}
}
}
Output: ààà
Expected Output: #C01=0155,INT=16:11,OUT=05:11
How do I retrive the expected output.
public class ExtractText
{
/**
* private constructor.
*/
private ExtractText()
{
//static class
}
public static void main( String[] args ) throws Exception
{
if(l!=null)
{
System.out.println("HERE"+l.length);
deleteSubs(op);
System.out.println("Then"+l.length);
}
else
{
System.out.println("WHERE");
}
File y=new File(imgDes);
if(!y.exists())
{
y.mkdirs();
}
File z=new File(imgDestination);
if(!z.exists())
{
z.mkdirs();
}
File fr=new File(outputFile);
if(!fr.isDirectory())
{
fr.delete();
}
// Defaults to text files
String ext = ".txt";
int startPage = 1;
int endPage = Integer.MAX_VALUE;
Writer output = null;
PDDocument document =null;
try
{
try
{
URL url = new URL( pdfFile );
document = PDDocument.load(url, force);
String fileName = url.getFile();
if( outputFile == null && fileName.length() >4)
{
outputFile = new File( fileName.substring( 0, fileName.length() -4 ) + ext ).getName();
}
}
catch( MalformedURLException e)
{
document = PDDocument.load(pdfFile, force);
if( outputFile == null && pdfFile.length() >4 )
{
outputFile = pdfFile.substring( 0, pdfFile.length() -4 ) + ext;
}
}
//document.print();
if( document.isEncrypted() )
{
StandardDecryptionMaterial sdm = new StandardDecryptionMaterial( password );
document.openProtection(sdm);
AccessPermission ap = document.getCurrentAccessPermission();
if( ! ap.canExtractContent() )
{
throw new IOException("You do not have permission to extract text" );
}
}
if ((encoding == null) && (toHTML))
{
encoding = "UTF-8";
}
if( toConsole )
{
output = new OutputStreamWriter(System.out);
}
else
{
if( encoding != null )
{
output = new OutputStreamWriter(new FileOutputStream( outputFile ), encoding );
}
else
{
//use default encoding
output = new OutputStreamWriter(new FileOutputStream( outputFile ) );
}
}
PDFTextStripper4 stripper = null;
if(toHTML)
{
stripper = new PDFText2HTML(encoding);
}
else
{
stripper = new PDFTextStripper4(encoding);
}
File f= new File(imgDestination);
PDDocument pd;
int i=0;
if(f.exists())
{
pd=PDDocument.load(pdfFile);
PDFontDescriptor fd;
fd = new PDFontDescriptorDictionary();
List<PDPage> li=pd.getDocumentCatalog().getAllPages();
for(PDPage page:li)
{
PDResources pdr=page.getResources();
Map<String, PDFont> m=pdr.getFonts();
PDStream pst;
for(PDFont pdd:m.values())
{
System.out.println("----------"+pdd.getBaseFont());
pdd.getFontDescriptor();
fd = pdd.getFontDescriptor();
pdd.setFontDescriptor((PDFontDescriptorDictionary)fd);
System.out.println("tititititi"+pdd.getFontEncoding());
if(pdd.isType1Font())
{
pst=((PDFontDescriptorDictionary) fd).getFontFile3();
System.out.println("In If "+pst);
if(pst!= null)
{
FileOutputStream fos = new FileOutputStream(new File(imgDestination+pdd.getBaseFont().toString()+".pfb"));
IOUtils.copy(pst.createInputStream(), fos);
i++;
System.out.println(i);
fos.close();
}
}
else
if(pdd.isTrueTypeFont())
{
pst= ((PDFontDescriptorDictionary) fd).getFontFile2();
System.out.println("In Else-if"+pst);
if (pst!= null)
{
FileOutputStream fos = new FileOutputStream(new File(imgDestination+pdd.getBaseFont().toString()+".ttf"));
IOUtils.copy(pst.createInputStream(), fos);
i++;
System.out.println(i);
fos.close();
}
}
else
if(pdd.isSymbolicFont())
{
System.out.println("Symbol.......");
}
else
{
System.out.println("In Else");
}
}
}
int pageCount = document.getDocumentCatalog().getAllPages().size();
for (int p = 0; p < pageCount; ++p)
{
System.out.println("I am in for loop");
stripper.setForceParsing( force );
stripper.setSortByPosition( true );
stripper.setShouldSeparateByBeads(separateBeads);
stripper.setStartPage( p);
stripper.setEndPage( p);
stripper.writeText( document, output );
FileOutputStream fos = new FileOutputStream(new File(f5+(p+1)+".html"));
output.close();
}
PDDocumentInformation info = document.getDocumentInformation();
System.out.println( "Page Count=" + document.getNumberOfPages());
System.out.println( "Title=" + info.getTitle());
System.out.println( "Author=" + info.getAuthor());
System.out.println( "Subject=" + info.getSubject() );
System.out.println( "Keywords=" + info.getKeywords() );
System.out.println( "Creator=" + info.getCreator() );
System.out.println( "Producer=" + info.getProducer() );
System.out.println( "Creation Date=" + info.getCreationDate() );
System.out.println( "Modification Date=" + info.getModificationDate());
System.out.println( "Trapped=" + info.getTrapped());
}
}catch(Exception e)
{
e.printStackTrace();
}
finally
{
if( output != null)
{
output.close();
}
if( document != null )
{
document.close();
}
}
}
private static void deleteSubs(File op)
{
// TODO Auto-generated method stub
File[] files = op.listFiles();
System.out.print("In delete folder");
if(files!=null)
{
//some JVMs return null for empty dirs
for(File f: files)
{
if(f.isDirectory())
{
deleteSubs(f);
}
else
{
f.delete();
}
}
}
op.delete();
}
}
now i am able to get entire pdf to a html file i.e.. I am extracting text only not images but i want to get every page of a pdf in to single html so any solution for this is quite helpful to me.. ThankYou
The answer is in your question: just set
stripper.setStartPage( p );
stripper.setEndPage( p );
accordingly. So you would loop somewhat like this:
int pageCount = document.getDocumentCatalog().getAllPages().size();
for (int p = 0; p < pageCount; ++p)
{
//... your options
stripper.setStartPage(p);
stripper.setEndPage(p);
FileOutputStream fos = new FileOutputStream(new File(f5+(p+1)+".html"));
stripper.writeText(document, fos);
fos.close();
}
Btw if you get an exception relating to the sorting comparator, use setSortByPosition(false), or wait for version 1.8.8 where this problem is fixed.
I am making this J2ME application but I am having some problem when I am trying to save I thinks that it save properly but I am not sure....but when I retrieve it gives null
This is how I am storing them
PAR par = new PAR(oldMonPay, newMonPay, oldInterest);
par.setOldMPay(oldMonPay);
par.setNewMPay(newMonPay);
par.setOldInt(oldInterest);
And this is how I saving and retrieving
public static byte[] parseObjPAR(PAR p) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out;
try {
out = new DataOutputStream(baos);
out.writeUTF(p.getNewMPay());
out.writeUTF(p.getOldInt());
out.writeUTF(p.getOldMPay());
} catch (IOException e) {
}
return baos.toByteArray();
}
public static PAR parseByteArrPAR(byte[] b) {
PAR p = null;
ByteArrayInputStream bais;
DataInputStream in;
if (b != null) {
try {
bais = new ByteArrayInputStream(b);
in = new DataInputStream(bais);
p = new PAR(
in.readUTF(),
in.readUTF(),
in.readUTF());
} catch (IOException e) {
}
}
return p;
}
This is how I displaying the retrieved information, there is another problem this thing is not showing all the data but is only showing the 3 records. I think the first 3.
public void populatePAResult(PAR[] p) {
try {
for (int i = 0; i < p.length; i++) {
String oldMP = p[i].getOldMPay();
String newMP = p[i].getNewMPay();
String oldI = p[i].getOldInt();
result1.append("Day : " + oldMP, null);
result1.append("Time : " + oldI, null);
result1.append("Technology : " + newMP, null);
}
} catch (Exception e) {
}
}
In the parseObjPAR method that writes the data the order is:
out.writeUTF(p.getNewMPay());
out.writeUTF(p.getOldInt());
out.writeUTF(p.getOldMPay());
whereas when you read it back in and pass the order the constructor is expecting is different:
PAR par = new PAR(oldMonPay, newMonPay, oldInterest);
so even if it wasn't null the loaded data would be invalid.
I am testing the feasibility of compressing some messaging between Java and C#.
The messaging used ranges from small strings (40bytes) to larger strings (4K).
I have found differences in the output of Java GZIP implementation to the dot Net GZIP implementation.
I'm guessing that dot Net has a larger header that is causing the large overhead.
I prefer the Java implementation as it works better on small strings, and would like the dot Net to achieve similar results.
Output, Java version 1.6.0_10
Text:EncodeDecode
Bytes:(12 bytes)RW5jb2RlRGVjb2Rl <- Base64
Compressed:(29)H4sIAAAAAAAAAHPNS85PSXVJBZEAd9jYdgwAAAA=
Decompressed:(12)RW5jb2RlRGVjb2Rl
Converted:EncodeDecode
Text:EncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecode
Bytes:(120)RW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2Rl
Compressed:(33)H4sIAAAAAAAAAHPNS85PSXVJBZGudGQDAOcKnrd4AAAA
Decompressed:(120)RW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2Rl
Converted:EncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecode
Output, dot Net 2.0.50727
Text:EncodeDecode
Bytes:(12)RW5jb2RlRGVjb2Rl
Compressed:(128)H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ik6X02qWP83x7/8Dd9jYdgwAAAA=
Decompressed:(12)RW5jb2RlRGVjb2Rl
Text:EncodeDecode
Text:EncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecode
Bytes:(120)RW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2Rl
Compressed:(131)H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ik6X02qWP83x7w/z9/8H5wqet3gAAAA=
Decompressed:(120)RW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2RlRW5jb2RlRGVjb2Rl
Text:EncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecodeEncodeDecode
How can I achieve the smaller sized encoding on the dot Net side?
Note,
Java implementation can decode dot Net implementation and
dot Net implementation can decode Java implementation.
Java Code
#Test
public void testEncodeDecode()
{
final String strTitle = "EncodeDecode";
try
{
debug( "Text:" + strTitle );
byte[] ba = strTitle.getBytes( "UTF-8" );
debug( "Bytes:" + toString( ba ) );
byte[] eba = encode_GZIP( ba );
debug( "Encoded:" + toString( eba ) );
byte[] ba2 = decode_GZIP( eba );
debug( "Decoded:" + toString( ba2 ) );
debug( "Converted:" + new String( ba2, "UTF-8" ) );
}
catch( Exception ex ) { fail( ex ); }
}
#Test
public void testEncodeDecode2()
{
final String strTitle = "EncodeDecode";
try
{
StringBuilder sb = new StringBuilder();
for( int i = 0 ; i < 10 ; i++ ) sb.append( strTitle );
debug( "Text:" + sb.toString() );
byte[] ba = sb.toString().getBytes( ENCODING );
debug( "Bytes:" + toString( ba ) );
byte[] eba = encode_GZIP( ba );
debug( "Encoded:" + toString( eba ) );
byte[] ba2 = decode_GZIP( eba );
debug( "Decoded:" + toString( ba2 ) );
debug( "Converted:" + new String( ba2, ENCODING ) );
}
catch( Exception ex ) { fail( ex ); }
}
private String toString( byte[] ba )
{
return "("+ba.length+")"+Base64.byteArrayToBase64( ba );
}
protected static byte[] encode_GZIP( byte[] baData ) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream( baData );
GZIPOutputStream zos = new GZIPOutputStream( baos );
byte[] baBuf = new byte[ 1024 ];
int nSize;
while( -1 != ( nSize = bais.read( baBuf ) ) )
{
zos.write( baBuf, 0, nSize );
zos.flush();
}
Utilities.closeQuietly( zos );
Utilities.closeQuietly( bais );
return baos.toByteArray();
}
protected static byte[] decode_GZIP( byte[] baData ) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bais = new ByteArrayInputStream( baData );
GZIPInputStream zis = new GZIPInputStream( bais );
byte[] baBuf = new byte[ 1024 ];
int nSize;
while( -1 != ( nSize = zis.read( baBuf ) ) )
{
baos.write( baBuf, 0, nSize );
baos.flush();
}
Utilities.closeQuietly( zis );
Utilities.closeQuietly( bais );
return baos.toByteArray();
}
private void debug( Object o ) { System.out.println( o ); }
private void fail( Exception ex )
{
ex.printStackTrace();
Assert.fail( ex.getMessage() );
}
dot Net Code
[Test]
public void TestJava6()
{
string strData = "EncodeDecode";
Console.WriteLine("Text:" + strData);
byte[] baData = Encoding.UTF8.GetBytes(strData);
Console.WriteLine("Bytes:" + toString(baData));
byte[] ebaData2 = encode_GZIP(baData);
Console.WriteLine("Encoded:" + toString(ebaData2));
byte[] baData2 = decode_GZIP(ebaData2);
Console.WriteLine("Decoded:" + toString(baData2));
Console.WriteLine("Text:" + Encoding.UTF8.GetString(baData2));
}
[Test]
public void TestJava7()
{
string strData = "EncodeDecode";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) sb.Append(strData);
Console.WriteLine("Text:" + sb.ToString());
byte[] baData = Encoding.UTF8.GetBytes(sb.ToString());
Console.WriteLine("Bytes:" + toString(baData));
byte[] ebaData2 = encode_GZIP(baData);
Console.WriteLine("Encoded:" + toString(ebaData2));
byte[] baData2 = decode_GZIP(ebaData2);
Console.WriteLine("Decoded:" + toString(baData2));
Console.WriteLine("Text:" + Encoding.UTF8.GetString(baData2));
}
public string toString(byte[] ba)
{
return "(" + ba.Length + ")" + Convert.ToBase64String(ba);
}
protected static byte[] decode_GZIP(byte[] ba)
{
MemoryStream writer = new MemoryStream();
using (GZipStream zis = new GZipStream(new MemoryStream(ba), CompressionMode.Decompress))
{
Utilities.CopyStream(zis, writer);
}
return writer.ToArray();
}
protected static byte[] encode_GZIP(byte[] ba)
{
using (MemoryStream reader = new MemoryStream(ba))
{
MemoryStream writer = new MemoryStream();
using (GZipStream zos = new GZipStream(writer, CompressionMode.Compress))
{
Utilities.CopyStream(reader, zos);
}
return writer.ToArray();
}
}
This is one of several bugs in the .NET gzip code. That code should be avoided. Use DotNetZip instead. See answer here: Why does my C# gzip produce a larger file than Fiddler or PHP? .
When I open a websocket connection to my websocket server application from Java, the server sees two connections. The first one never sends any data and the second one sends all the proper headers, etc. Anyone know what the reason for this is?
Client side connection is:
var websocket = new WebSocket( "ws://192.168.1.19:3333/websession" );
On the server side, in a while loop I call "serverSocket.accept()" and this gets called twice. But one of them never sends any data (the in.read() simply times out eventually without returning anything).
JAVA SERVER CODE
import java.net.*;
import java.io.*;
import java.security.*;
public class WebListener {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening) new ServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
class ServerThread extends Thread {
private Socket socket = null;
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
public void run() {
try {
OutputStream outStream = null;
PrintWriter out = new PrintWriter( outStream = socket.getOutputStream(), true);
BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream()));
String inputLine, outputLine;
//Handle the headers first
doHeaders( out, in );
// ..elided..
out.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void doHeaders(PrintWriter out, BufferedReader in) throws Exception {
String inputLine = null;
String key = null;
//Read the headers
while ( ( inputLine = in.readLine() ) != null ) {
//Get the key
if ( inputLine.startsWith( "Sec-WebSocket-Key" ) )
key = inputLine.substring( "Sec-WebSocket-Key: ".length() );
//They're done
if ( inputLine.equals( "" ) ) break;
}
//We need a key to continue
if ( key == null ) throw new Exception( "No Sec-WebSocket-Key was passed!" );
//Send our headers
out.println( "HTTP/1.1 101 Web Socket Protocol Handshake\r" );
out.println( "Upgrade: websocket\r" );
out.println( "Connection: Upgrade\r" );
out.println( "Sec-WebSocket-Accept: " + createOK( key ) + "\r" );
out.println( "\r" );
}
public String createOK(String key) throws NoSuchAlgorithmException, UnsupportedEncodingException, Exception {
String uid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String text = key + uid;
MessageDigest md = MessageDigest.getInstance( "SHA-1" );
byte[] sha1hash = new byte[40];
md.update( text.getBytes("iso-8859-1"), 0, text.length());
sha1hash = md.digest();
return new String( base64( sha1hash ) );
}
public byte[] base64(byte[] bytes) throws Exception {
ByteArrayOutputStream out_bytes = new ByteArrayOutputStream();
OutputStream out = new Base64.OutputStream(out_bytes); //Using http://iharder.net/base64
out.write(bytes);
out.close();
return out_bytes.toByteArray();
}
private String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
}
This looks to be a bug with Firefox. In Chrome it only opens one connection, while the same page in Firefox 15 opens two connections.