Java stream socket can only send once - java

I'm writing a simple download accelerator. The problem is I can send and receive messages once. The next time I try to send and receive message, I get no response froms server. I'm not even sure if I am able to send the second message.
The first message is something like;
*HEAD /TIPS/LAWLER/PANOHOW2.PDF HTTP/1.0\r\n
HTTP/1.0\r\n
Connection: close\r\n
\r\n*
and response is;
*HTTP/1.1 200 OK
Date: Mon, 24 Jan 2011 10:53:38 GMT
Server: Apache
Last-Modified: Tue,
22 Sep 1998 13:19:52 GMT
ETag: "1968013-2b4f4-3386e15b6ee00"
Accept-Ranges: bytes
Content-Length: 177396
Connection: close
Content-Type: application/pdf*
When i attemp to sen message;
GET /TIPS/LAWLER/hedeh/PANOHOW2.PDF HTTP/1.0\r\n
Range: bytes=0-44349\r\n
Connection: close\r\n
\r\n
I get nothing.
What is wrong with my code?
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//Parse URL
String cmd = "http://www.imaging-resource.com"; //Host Name
if (cmd.contains("http://"))
{
cmd = cmd.substring(7); //
if (cmd.contains("/"))
{
int index = cmd.indexOf("/");
cmd = cmd.substring(0, index);
System.out.println(cmd);
}
}
String str = "HEAD /TIPS/LAWLER/PANOHOW2.PDF HTTP/1.0\r\nConnection: close\r\n\r\n"; //First message to send
//Create socket, connect, initialize read and write handlers
//in, out
Socket socket = null; //Create a client socket
SocketAddress sockaddr = null;
InetAddress address = null;
InputStream input = null; //Input handler
OutputStream output = null; //Output handler
try
{
address = InetAddress.getByName(cmd); //Get ip using host name
socket = new Socket(); //Contrusct Socket
sockaddr = new InetSocketAddress(address, 80);
//socket.setTcpNoDelay(false);
socket.connect(sockaddr, 2000); //Connect to server set and timeout to 2 sec
} //End of try Block
catch (Exception ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
System.out.println(ex);
} //End of catch Block
if (!socket.isConnected())
{
System.out.println("not connected");
System.exit(-1);
}
//Sending package here
try
{
int c;
byte[] buf = new byte[65535];
char[] chr = new char[65535];
input = socket.getInputStream(); //Input handler is created
output = socket.getOutputStream(); //Output handler is created
buf = str.getBytes(); //HEAD message converted into byte array
output.write(buf); //Sending message to server
output.flush();
int counter = 0;
while ((c = input.read()) != -1) //Reading received package
chr[counter++]=(char)c;
//input.reset();
str = new String(chr); //For better manipulation, server message is converted to string
System.out.println(str);
} catch (IOException e)
{
System.err.print(e);
} //End of catch
int index = str.indexOf("Content-Length"); //Look for "Content-Length" in response
str = str.substring(index); //Using its beginning index create an substring
index = str.indexOf("\r\n"); //Search for end of line
str = str.substring(0, index); //Erase end if line chars - \r\n
str = str.substring(16, str.length()); //"Content-Length: " 16 chars
int fileSize = Integer.parseInt(str); //Lentgh of file is converted to Integer
int[][] parts = new int[4][2]; //Beginning and en of jobs for threads will be stored here
int remainder = fileSize; //Bytes left to split for rest of the threads will be stored here
int start = 0;
int finish = 0;
for (int i = 0; i < 4; i++) //Number of threads many times
{
parts[i][0] = start; //*******Each threads job Interval(eg. 0-108)
//System.out.print(parts[i][0] + "-"); //******
finish += remainder / 4 - i; //*****
parts[i][1] = finish; //****
start = finish + 1; //***
if (i + 1 == 4)
parts[i][1] = fileSize; //*
}
str = "GET /TIPS/LAWLER/hedeh/PANOHOW2.PDF HTTP/1.0\r\nRange: bytes=" + parts[0][0] + "-" + parts[0][1] + "\r\nConnection: close\r\n\r\n";
//System.out.println(str);
if(!socket.isConnected())
{
System.out.println("closed");
try
{
socket.connect(sockaddr, 2000);
}//End od try
catch(Exception e){
System.err.print(e);
}//End of catch
}//End of If
System.out.println("Is Outputhandler closed :"+socket.isOutputShutdown());
System.out.println("Is Inputhandler closed :"+socket.isInputShutdown());
try
{
int c;
byte[] buf = new byte[65535];
char[] chr = new char[65535];
buf = str.getBytes(); //Output handler is created
output.write(buf); //Sending message to server
output.flush();
int counter = 0;
if((c = input.read()) != -1)
{
chr[counter++] = (char) c;
while ((c = input.read()) != -1) //Reading received package
{
System.out.println("response is not -1");
chr[counter++]=(char)c;
}
str = new String(chr); //For better manipulation, serve message is converted to string
System.out.println("Response "+str);
}//End of If
else System.out.println("No Response!");
}catch(Exception e)
{System.err.print(e);}
//Closing open stuff
try {
output.close();
input.close();
socket.close();
} catch (Exception e) {
System.out.println(e);
}
}// End of main method
}//End of class definition

The first message is something like;
HTTP/1.0\r\n
You have to use HTTP version 1.1 to use multiple requests on a single TCP connection.
From the Wikipedia article on HTTP:
In HTTP/0.9 and 1.0, the connection is closed after a single request/response pair. In HTTP/1.1 a keep-alive-mechanism was introduced, where a connection could be reused for more than one request.
Also, as #Joachim Sauer points out in the comments, you're explicitly saying Connection: close in your header. :-)

I think that the problem is that you are trying to connect to HTTP server using plain TCP socket. Yes, HTTP is on top of TCP but it is complicated protocol that requires a lot of things to know. I'd suggest you to work with higher level API that implements HTTP protocol and provides you more convenient API.
The simplest example is URL+URLConnection from JDK. Probably better is HttpClient from Jakarta.

Related

Receiving byte packets by TCP

i have some problem with receive byte packets by TCP in JAVA.
My TCPServer class sending 207 - byte packets. When I send one packet, program display in console "Read 207 byte packet." and stops. With next packet it continue execution, display "Multiple Measurement" and
"Read 1868767867 byte packet.". After that receiving is stopped forever. I don't know why 1868767867 bytes it receive. I check it in wireshark and server sending always 207 bytes.
This is my TCPClient class:
public class TCPClient extends Thread {
private ServerSocket serverSocket;
private Socket connectionSocket;
private InputStream inputStream;
private DataInputStream dataInputStream;
public TCPClient() throws IOException {
try {
serverSocket = new ServerSocket(Config.TCP_PORT);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
connectionSocket = serverSocket.accept();
inputStream = connectionSocket.getInputStream();
dataInputStream = new DataInputStream(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
JsonObject json = getJsonFromTcp();
if (json != null) {
String command = json.getAsJsonPrimitive("command").getAsString();
if(command.equals("multipleMeasurement")) {
executeMultipleMeasurement();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private JsonObject getJsonFromTcp() throws IOException {
byte[] buff = new byte[4];
for(int i = 0; i < 4; i++) {
buff[i] = dataInputStream.readByte();
}
int len = (((buff[3] & 0xff) << 24) | ((buff[2] & 0xff) << 16) | ((buff[1] & 0xff) << 8) | (buff[0] & 0xff));
if(len > 0) {
System.out.println("Read " + len + " byte packet.");
byte[] data = new byte[len];
dataInputStream.readFully(data);
String jsonString = new String(data, "UTF-8");
JsonParser jsonParser = new JsonParser();
JsonObject json = jsonParser.parse(jsonString).getAsJsonObject();
return json;
}
return null;
}
private void executeMultipleMeasurement() {
System.out.println("Multiple Measurement");
}
}
Anyone know solution?
Looking at the number 1868767867, its bytes are
"%c%c%c%c" % (0x7b,0x22,0x63,0x6f)
'{"co'
So you could be reading the first four bytes of the next message as the length of the message. The most likely explanation given the claim that the server sends exactly 207 bytes each time is that the server includes the length of the length prefix (4 bytes) in the total message length. Depending on the intended protocol, it might be appropriate to read (length - 4) bytes as the body of the packet.
// Account for the length of the header
len -= 4;
if(len > 0) {
System.out.println("Read " + len + " byte packet.");
byte[] data = new byte[len];
dataInputStream.readFully(data);
A second possibility is that the server is measuring the number of characters in a string and then using that length as the length of the utf-8 converted byte buffer that it will send, including some non-ascii characters that cause the resulting buffer to be longer.
Without seeing the server code, it's impossible to be certain which is happening here.

Reliable UDP in java

I am working on my assignment to make UDP reliable using java. How can i add Timeout and re-transmission to handle data-grams that are discarded and add Sequence numbers so the client can verify that a reply is for the appropriate request ??
this is client code
import java.net.*;
import java.io.*;
public class EchoClient {
// UDP port to which service is bound
public static final int SERVICE_PORT = 7;
// Max size of packet
public static final int BUFSIZE = 256;
public static void main(String args[]){
if (args.length != 1)
{
System.err.println ("Syntax - java EchoClient hostname");
return;
}
String hostname = args[0];
// Get an InetAddress for the specified hostname
InetAddress addr = null;
try
{
// Resolve the hostname to an InetAddr
addr = InetAddress.getByName(hostname);
}
catch (UnknownHostException uhe)
{
System.err.println ("Unable to resolve host");
return;
}
try
{
// Bind to any free port
DatagramSocket socket = new DatagramSocket();
// Set a timeout value of two seconds
socket.setSoTimeout (2 * 1000);
for (int i = 1 ; i <= 10; i++)
{
// Copy some data to our packet
String message = "Packet number " + i ;
char[] cArray = message.toCharArray();
byte[] sendbuf = new byte[cArray.length];
for (int offset = 0; offset < cArray.length ; offset++)
{
sendbuf[offset] = (byte) cArray[offset];
}
// Create a packet to send to the UDP server
DatagramPacket sendPacket = new DatagramPacket(sendbuf, cArray.length, addr, SERVICE_PORT);
System.out.println ("Sending packet to " + hostname);
// Send the packet
socket.send (sendPacket);
System.out.print ("Waiting for packet.... ");
// Create a small packet for receiving UDP packets
byte[] recbuf = new byte[BUFSIZE];
DatagramPacket receivePacket = new DatagramPacket(recbuf, BUFSIZE);
// Declare a timeout flag
boolean timeout = false;
// Catch any InterruptedIOException that is thrown
// while waiting to receive a UDP packet
try
{
socket.receive (receivePacket);
}
catch (InterruptedIOException ioe)
{
timeout = true;
}
if (!timeout)
{
System.out.println ("packet received!");
System.out.println ("Details : " + receivePacket.getAddress() );
// Obtain a byte input stream to read the UDP packet
ByteArrayInputStream bin = new ByteArrayInputStream (
receivePacket.getData(), 0, receivePacket.getLength() );
// Connect a reader for easier access
BufferedReader reader = new BufferedReader (
new InputStreamReader ( bin ) );
// Loop indefinitely
for (;;)
{
String line = reader.readLine();
// Check for end of data
if (line == null)
break;
else
System.out.println (line);
}
}
else
{
System.out.println ("packet lost!");
}
// Sleep for a second, to allow user to see packet
try
{
Thread.sleep(1000);
}catch (InterruptedException ie) {}
}
}
catch (IOException ioe)
{
System.err.println ("Socket error " + ioe);
}
}
}
What you can do is adding import TCP headers like sequence number, windows into the UDP message body to make it more like TCP. Here is the a solution that might help you.

Java sending handshake packets to minecraft server

I have been working on a java program that basically acts like Minechat(text-based app to just view chat.) I have never really worked with networking too much, so the issue is figuring out how to send packets correctly. I am currently at the position of creating the handshake with the server. After hours of research, I have come up with the following code, but it always runs into the "Failed! (Exception)" message. To me, everything looks correct, but for all I know it could be 100% wrong. If someone could point out what I'm doing wrong here, I'd really appreciate it.
For reference, feel free to use this and this.
public static void main(String[] args) throws IOException {
host = new InetSocketAddress("162.244.165.111", 48040);
socket = new Socket();
System.out.println("Connecting...");
socket.connect(host, 3000);
System.out.println("Done!");
System.out.println("Making streams...");
output = new DataOutputStream(socket.getOutputStream());
input = new DataInputStream(socket.getInputStream());
System.out.println("Done!");
System.out.println("Attempting handshake... "+host.getAddress().toString().substring(1));
byte[] msg = ("47;"+host.getAddress().toString().substring(1)+";"+host.getPort()+";2;").getBytes(Charset.forName("UTF-16"));
output.writeInt(msg.length+Integer.valueOf(0x00));
output.writeByte(0x00);
output.write(msg);
output.flush();
try {
if (input.readByte() != 0x02)
System.out.println("Failed!");
else
System.out.println("Done!");
} catch (EOFException e) {
System.out.println("Failed! (Exception)");
}
}
EDIT:
More research suggests I use a Byte array, but this confuses me on how to represent a string and using strings is required?
Looking at this page http://wiki.vg/Protocol it looks like your not writing enough data nor in the right order. You also need to be using varint which is a special type of data representation of an integer.
Relevant links to this issue:
Handshake Protocol
Packet format
Server Ping Explanation and Example (which involves handshake)
The status ping works as follows:
C->S : Handshake State=1
C->S : Request
S->C : Response
C->S : Ping
S->C : Pong
C is client and S is server
Using the wiki and the provided code samples I modified your code to follow the entire status request.
public static void main(String [] args) throws IOException {
String address = "162.244.165.111";
int port = 48040;
InetSocketAddress host = new InetSocketAddress(address, port);
Socket socket = new Socket();
System.out.println("Connecting...");
socket.connect(host, 3000);
System.out.println("Done!");
System.out.println("Making streams...");
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
System.out.println("Done!");
System.out.println("Attempting handshake... "+host.getAddress().toString());
byte [] handshakeMessage = createHandshakeMessage(address, port);
// C->S : Handshake State=1
// send packet length and packet
writeVarInt(output, handshakeMessage.length);
output.write(handshakeMessage);
// C->S : Request
output.writeByte(0x01); //size is only 1
output.writeByte(0x00); //packet id for ping
// S->C : Response
int size = readVarInt(input);
int packetId = readVarInt(input);
if (packetId == -1) {
throw new IOException("Premature end of stream.");
}
if (packetId != 0x00) { //we want a status response
throw new IOException("Invalid packetID");
}
int length = readVarInt(input); //length of json string
if (length == -1) {
throw new IOException("Premature end of stream.");
}
if (length == 0) {
throw new IOException("Invalid string length.");
}
byte[] in = new byte[length];
input.readFully(in); //read json string
String json = new String(in);
// C->S : Ping
long now = System.currentTimeMillis();
output.writeByte(0x09); //size of packet
output.writeByte(0x01); //0x01 for ping
output.writeLong(now); //time!?
// S->C : Pong
readVarInt(input);
packetId = readVarInt(input);
if (packetId == -1) {
throw new IOException("Premature end of stream.");
}
if (packetId != 0x01) {
throw new IOException("Invalid packetID");
}
long pingtime = input.readLong(); //read response
// print out server info
System.out.println(json);
System.out.println("Done!");
}
public static byte [] createHandshakeMessage(String host, int port) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream handshake = new DataOutputStream(buffer);
handshake.writeByte(0x00); //packet id for handshake
writeVarInt(handshake, 4); //protocol version
writeString(handshake, host, StandardCharsets.UTF_8);
handshake.writeShort(port); //port
writeVarInt(handshake, 1); //state (1 for handshake)
return buffer.toByteArray();
}
public static void writeString(DataOutputStream out, String string, Charset charset) throws IOException {
byte [] bytes = string.getBytes(charset);
writeVarInt(out, bytes.length);
out.write(bytes);
}
public static void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
while (true) {
if ((paramInt & 0xFFFFFF80) == 0) {
out.writeByte(paramInt);
return;
}
out.writeByte(paramInt & 0x7F | 0x80);
paramInt >>>= 7;
}
}
public static int readVarInt(DataInputStream in) throws IOException {
int i = 0;
int j = 0;
while (true) {
int k = in.readByte();
i |= (k & 0x7F) << j++ * 7;
if (j > 5) throw new RuntimeException("VarInt too big");
if ((k & 0x80) != 128) break;
}
return i;
}

Java Tunnel HTTPS(SSL) Requests

I am writing a java application to serve as a local proxy. I have been helped greatly by this piece of code from http://www.nsftools.com/tips/jProxy.java. See program below:
/* <!-- in case someone opens this in a browser... --> <pre> */
/*
* This is a simple multi-threaded Java proxy server
* for HTTP requests (HTTPS doesn't seem to work, because
* the CONNECT requests aren't always handled properly).
* I implemented the class as a thread so you can call it
* from other programs and kill it, if necessary (by using
* the closeSocket() method).
*
* We'll call this the 1.1 version of this class. All I
* changed was to separate the HTTP header elements with
* \r\n instead of just \n, to comply with the official
* HTTP specification.
*
* This can be used either as a direct proxy to other
* servers, or as a forwarding proxy to another proxy
* server. This makes it useful if you want to monitor
* traffic going to and from a proxy server (for example,
* you can run this on your local machine and set the
* fwdServer and fwdPort to a real proxy server, and then
* tell your browser to use "localhost" as the proxy, and
* you can watch the browser traffic going in and out).
*
* One limitation of this implementation is that it doesn't
* close the ProxyThread socket if the client disconnects
* or the server never responds, so you could end up with
* a bunch of loose threads running amuck and waiting for
* connections. As a band-aid, you can set the server socket
* to timeout after a certain amount of time (use the
* setTimeout() method in the ProxyThread class), although
* this can cause false timeouts if a remote server is simply
* slow to respond.
*
* Another thing is that it doesn't limit the number of
* socket threads it will create, so if you use this on a
* really busy machine that processed a bunch of requests,
* you may have problems. You should use thread pools if
* you're going to try something like this in a "real"
* application.
*
* Note that if you're using the "main" method to run this
* by itself and you don't need the debug output, it will
* run a bit faster if you pipe the std output to 'nul'.
*
* You may use this code as you wish, just don't pretend
* that you wrote it yourself, and don't hold me liable for
* anything that it does or doesn't do. If you're feeling
* especially honest, please include a link to nsftools.com
* along with the code. Thanks, and good luck.
*
* Julian Robichaux -- http://www.nsftools.com
*/
import java.io.*;
import java.net.*;
import java.lang.reflect.Array;
public class jProxy extends Thread
{
public static final int DEFAULT_PORT = 8080;
private ServerSocket server = null;
private int thisPort = DEFAULT_PORT;
private String fwdServer = "";
private int fwdPort = 0;
private int ptTimeout = ProxyThread.DEFAULT_TIMEOUT;
private int debugLevel = 0;
private PrintStream debugOut = System.out;
/* here's a main method, in case you want to run this by itself */
public static void main (String args[])
{
int port = 0;
String fwdProxyServer = "";
int fwdProxyPort = 0;
if (args.length == 0)
{
System.err.println("USAGE: java jProxy <port number> [<fwd proxy> <fwd port>]");
System.err.println(" <port number> the port this service listens on");
System.err.println(" <fwd proxy> optional proxy server to forward requests to");
System.err.println(" <fwd port> the port that the optional proxy server is on");
System.err.println("\nHINT: if you don't want to see all the debug information flying by,");
System.err.println("you can pipe the output to a file or to 'nul' using \">\". For example:");
System.err.println(" to send output to the file prox.txt: java jProxy 8080 > prox.txt");
System.err.println(" to make the output go away: java jProxy 8080 > nul");
return;
}
// get the command-line parameters
port = Integer.parseInt(args[0]);
if (args.length > 2)
{
fwdProxyServer = args[1];
fwdProxyPort = Integer.parseInt(args[2]);
}
// create and start the jProxy thread, using a 20 second timeout
// value to keep the threads from piling up too much
System.err.println(" ** Starting jProxy on port " + port + ". Press CTRL-C to end. **\n");
jProxy jp = new jProxy(port, fwdProxyServer, fwdProxyPort, 20);
jp.setDebug(1, System.out); // or set the debug level to 2 for tons of output
jp.start();
// run forever; if you were calling this class from another
// program and you wanted to stop the jProxy thread at some
// point, you could write a loop that waits for a certain
// condition and then calls jProxy.closeSocket() to kill
// the running jProxy thread
while (true)
{
try { Thread.sleep(3000); } catch (Exception e) {}
}
// if we ever had a condition that stopped the loop above,
// we'd want to do this to kill the running thread
//jp.closeSocket();
//return;
}
/* the proxy server just listens for connections and creates
* a new thread for each connection attempt (the ProxyThread
* class really does all the work)
*/
public jProxy (int port)
{
thisPort = port;
}
public jProxy (int port, String proxyServer, int proxyPort)
{
thisPort = port;
fwdServer = proxyServer;
fwdPort = proxyPort;
}
public jProxy (int port, String proxyServer, int proxyPort, int timeout)
{
thisPort = port;
fwdServer = proxyServer;
fwdPort = proxyPort;
ptTimeout = timeout;
}
/* allow the user to decide whether or not to send debug
* output to the console or some other PrintStream
*/
public void setDebug (int level, PrintStream out)
{
debugLevel = level;
debugOut = out;
}
/* get the port that we're supposed to be listening on
*/
public int getPort ()
{
return thisPort;
}
/* return whether or not the socket is currently open
*/
public boolean isRunning ()
{
if (server == null)
return false;
else
return true;
}
/* closeSocket will close the open ServerSocket; use this
* to halt a running jProxy thread
*/
public void closeSocket ()
{
try {
// close the open server socket
server.close();
// send it a message to make it stop waiting immediately
// (not really necessary)
/*Socket s = new Socket("localhost", thisPort);
OutputStream os = s.getOutputStream();
os.write((byte)0);
os.close();
s.close();*/
} catch(Exception e) {
if (debugLevel > 0)
debugOut.println(e);
}
server = null;
}
public void run()
{
try {
// create a server socket, and loop forever listening for
// client connections
server = new ServerSocket(thisPort);
if (debugLevel > 0)
debugOut.println("Started jProxy on port " + thisPort);
while (true)
{
Socket client = server.accept();
ProxyThread t = new ProxyThread(client, fwdServer, fwdPort);
t.setDebug(debugLevel, debugOut);
t.setTimeout(ptTimeout);
t.start();
}
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("jProxy Thread error: " + e);
}
closeSocket();
}
}
/*
* The ProxyThread will take an HTTP request from the client
* socket and send it to either the server that the client is
* trying to contact, or another proxy server
*/
class ProxyThread extends Thread
{
private Socket pSocket;
private String fwdServer = "";
private int fwdPort = 0;
private int debugLevel = 0;
private PrintStream debugOut = System.out;
// the socketTimeout is used to time out the connection to
// the remote server after a certain period of inactivity;
// the value is in milliseconds -- use zero if you don't want
// a timeout
public static final int DEFAULT_TIMEOUT = 20 * 1000;
private int socketTimeout = DEFAULT_TIMEOUT;
public ProxyThread(Socket s)
{
pSocket = s;
}
public ProxyThread(Socket s, String proxy, int port)
{
pSocket = s;
fwdServer = proxy;
fwdPort = port;
}
public void setTimeout (int timeout)
{
// assume that the user will pass the timeout value
// in seconds (because that's just more intuitive)
socketTimeout = timeout * 1000;
}
public void setDebug (int level, PrintStream out)
{
debugLevel = level;
debugOut = out;
}
public void run()
{
try
{
long startTime = System.currentTimeMillis();
// client streams (make sure you're using streams that use
// byte arrays, so things like GIF and JPEG files and file
// downloads will transfer properly)
BufferedInputStream clientIn = new BufferedInputStream(pSocket.getInputStream());
BufferedOutputStream clientOut = new BufferedOutputStream(pSocket.getOutputStream());
// the socket to the remote server
Socket server = null;
// other variables
byte[] request = null;
byte[] response = null;
int requestLength = 0;
int responseLength = 0;
int pos = -1;
StringBuffer host = new StringBuffer("");
String hostName = "";
int hostPort = 80;
// get the header info (the web browser won't disconnect after
// it's sent a request, so make sure the waitForDisconnect
// parameter is false)
request = getHTTPData(clientIn, host, false);
requestLength = Array.getLength(request);
// separate the host name from the host port, if necessary
// (like if it's "servername:8000")
hostName = host.toString();
pos = hostName.indexOf(":");
if (pos > 0)
{
try { hostPort = Integer.parseInt(hostName.substring(pos + 1));
} catch (Exception e) { }
hostName = hostName.substring(0, pos);
}
// either forward this request to another proxy server or
// send it straight to the Host
try
{
if ((fwdServer.length() > 0) && (fwdPort > 0))
{
server = new Socket(fwdServer, fwdPort);
} else {
server = new Socket(hostName, hostPort);
}
} catch (Exception e) {
// tell the client there was an error
String errMsg = "HTTP/1.0 500\nContent Type: text/plain\n\n" +
"Error connecting to the server:\n" + e + "\n";
clientOut.write(errMsg.getBytes(), 0, errMsg.length());
}
if (server != null)
{
server.setSoTimeout(socketTimeout);
BufferedInputStream serverIn = new BufferedInputStream(server.getInputStream());
BufferedOutputStream serverOut = new BufferedOutputStream(server.getOutputStream());
// send the request out
serverOut.write(request, 0, requestLength);
serverOut.flush();
// and get the response; if we're not at a debug level that
// requires us to return the data in the response, just stream
// it back to the client to save ourselves from having to
// create and destroy an unnecessary byte array. Also, we
// should set the waitForDisconnect parameter to 'true',
// because some servers (like Google) don't always set the
// Content-Length header field, so we have to listen until
// they decide to disconnect (or the connection times out).
if (debugLevel > 1)
{
response = getHTTPData(serverIn, true);
responseLength = Array.getLength(response);
} else {
responseLength = streamHTTPData(serverIn, clientOut, true);
}
serverIn.close();
serverOut.close();
}
// send the response back to the client, if we haven't already
if (debugLevel > 1)
clientOut.write(response, 0, responseLength);
// if the user wants debug info, send them debug info; however,
// keep in mind that because we're using threads, the output won't
// necessarily be synchronous
if (debugLevel > 0)
{
long endTime = System.currentTimeMillis();
debugOut.println("Request from " + pSocket.getInetAddress().getHostAddress() +
" on Port " + pSocket.getLocalPort() +
" to host " + hostName + ":" + hostPort +
"\n (" + requestLength + " bytes sent, " +
responseLength + " bytes returned, " +
Long.toString(endTime - startTime) + " ms elapsed)");
debugOut.flush();
}
if (debugLevel > 1)
{
debugOut.println("REQUEST:\n" + (new String(request)));
debugOut.println("RESPONSE:\n" + (new String(response)));
debugOut.flush();
}
// close all the client streams so we can listen again
clientOut.close();
clientIn.close();
pSocket.close();
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error in ProxyThread: " + e);
//e.printStackTrace();
}
}
private byte[] getHTTPData (InputStream in, boolean waitForDisconnect)
{
// get the HTTP data from an InputStream, and return it as
// a byte array
// the waitForDisconnect parameter tells us what to do in case
// the HTTP header doesn't specify the Content-Length of the
// transmission
StringBuffer foo = new StringBuffer("");
return getHTTPData(in, foo, waitForDisconnect);
}
private byte[] getHTTPData (InputStream in, StringBuffer host, boolean waitForDisconnect)
{
// get the HTTP data from an InputStream, and return it as
// a byte array, and also return the Host entry in the header,
// if it's specified -- note that we have to use a StringBuffer
// for the 'host' variable, because a String won't return any
// information when it's used as a parameter like that
ByteArrayOutputStream bs = new ByteArrayOutputStream();
streamHTTPData(in, bs, host, waitForDisconnect);
return bs.toByteArray();
}
private int streamHTTPData (InputStream in, OutputStream out, boolean waitForDisconnect)
{
StringBuffer foo = new StringBuffer("");
return streamHTTPData(in, out, foo, waitForDisconnect);
}
private int streamHTTPData (InputStream in, OutputStream out,
StringBuffer host, boolean waitForDisconnect)
{
// get the HTTP data from an InputStream, and send it to
// the designated OutputStream
StringBuffer header = new StringBuffer("");
String data = "";
int responseCode = 200;
int contentLength = 0;
int pos = -1;
int byteCount = 0;
try
{
// get the first line of the header, so we know the response code
data = readLine(in);
if (data != null)
{
header.append(data + "\r\n");
pos = data.indexOf(" ");
if ((data.toLowerCase().startsWith("http")) &&
(pos >= 0) && (data.indexOf(" ", pos+1) >= 0))
{
String rcString = data.substring(pos+1, data.indexOf(" ", pos+1));
try
{
responseCode = Integer.parseInt(rcString);
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error parsing response code " + rcString);
}
}
}
// get the rest of the header info
while ((data = readLine(in)) != null)
{
// the header ends at the first blank line
if (data.length() == 0)
break;
header.append(data + "\r\n");
// check for the Host header
pos = data.toLowerCase().indexOf("host:");
if (pos >= 0)
{
host.setLength(0);
host.append(data.substring(pos + 5).trim());
}
// check for the Content-Length header
pos = data.toLowerCase().indexOf("content-length:");
if (pos >= 0)
contentLength = Integer.parseInt(data.substring(pos + 15).trim());
}
// add a blank line to terminate the header info
header.append("\r\n");
// convert the header to a byte array, and write it to our stream
out.write(header.toString().getBytes(), 0, header.length());
// if the header indicated that this was not a 200 response,
// just return what we've got if there is no Content-Length,
// because we may not be getting anything else
if ((responseCode != 200) && (contentLength == 0))
{
out.flush();
return header.length();
}
// get the body, if any; we try to use the Content-Length header to
// determine how much data we're supposed to be getting, because
// sometimes the client/server won't disconnect after sending us
// information...
if (contentLength > 0)
waitForDisconnect = false;
if ((contentLength > 0) || (waitForDisconnect))
{
try {
byte[] buf = new byte[4096];
int bytesIn = 0;
while ( ((byteCount < contentLength) || (waitForDisconnect))
&& ((bytesIn = in.read(buf)) >= 0) )
{
out.write(buf, 0, bytesIn);
byteCount += bytesIn;
}
} catch (Exception e) {
String errMsg = "Error getting HTTP body: " + e;
if (debugLevel > 0)
debugOut.println(errMsg);
//bs.write(errMsg.getBytes(), 0, errMsg.length());
}
}
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error getting HTTP data: " + e);
}
//flush the OutputStream and return
try { out.flush(); } catch (Exception e) {}
return (header.length() + byteCount);
}
private String readLine (InputStream in)
{
// reads a line of text from an InputStream
StringBuffer data = new StringBuffer("");
int c;
try
{
// if we have nothing to read, just return null
in.mark(1);
if (in.read() == -1)
return null;
else
in.reset();
while ((c = in.read()) >= 0)
{
// check for an end-of-line character
if ((c == 0) || (c == 10) || (c == 13))
break;
else
data.append((char)c);
}
// deal with the case where the end-of-line terminator is \r\n
if (c == 13)
{
in.mark(1);
if (in.read() != 10)
in.reset();
}
} catch (Exception e) {
if (debugLevel > 0)
debugOut.println("Error getting header: " + e);
}
// and return what we have
return data.toString();
}
}
Problem is secure sites like "https://www.google.com" don't work. I have tried to tweak the code over and over again but all to no avail. I have gone through questions answered here and many more sites too but I just cant seem to get it to work. I would av posted links but I cant cos I dnt av enuf reputation yet.
Someone pls help me with what needs to be done to support Secure Sites(HTTPS).
Thanks in advance.
PS: Sorry if I didn't ask the question the right way.I'm a newbie. Cheers...
Default port for https is 443. This is used if no port is specified in the URL, as is the case with the google site you give as an example. Try adjusting the code with this in mind.

How to read all of Inputstream in Server Socket JAVA

I am using Java.net at one of my project.
and I wrote a App Server that gets inputStream from a client.
But some times my (buffered)InputStream can not get all of OutputStream that client sent to my server.
How can I write a wait or some thing like that, that my InputStream gets all of the OutputStream of client?
(My InputStream is not a String)
private Socket clientSocket;
private ServerSocket server;
private BufferedOutputStream outputS;
private BufferedInputStream inputS;
private InputStream inBS;
private OutputStream outBS;
server = new ServerSocket(30501, 100);
clientSocket = server.accept();
public void getStreamFromClient() {
try {
outBS = clientSocket.getOutputStream();
outputS = new BufferedOutputStream( outBS);
outputS.flush();
inBS = clientSocket.getInputStream();
inputS = new BufferedInputStream( inBS );
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks.
The problem you have is related to TCP streaming nature.
The fact that you sent 100 Bytes (for example) from the server doesn't mean you will read 100 Bytes in the client the first time you read. Maybe the bytes sent from the server arrive in several TCP segments to the client.
You need to implement a loop in which you read until the whole message was received.
Let me provide an example with DataInputStream instead of BufferedinputStream. Something very simple to give you just an example.
Let's suppose you know beforehand the server is to send 100 Bytes of data.
In client you need to write:
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
while(!end)
{
int bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length == 100)
{
end = true;
}
}
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
Now, typically the data size sent by one node (the server here) is not known beforehand. Then you need to define your own small protocol for the communication between server and client (or any two nodes) communicating with TCP.
The most common and simple is to define TLV: Type, Length, Value. So you define that every message sent form server to client comes with:
1 Byte indicating type (For example, it could also be 2 or whatever).
1 Byte (or whatever) for length of message
N Bytes for the value (N is indicated in length).
So you know you have to receive a minimum of 2 Bytes and with the second Byte you know how many following Bytes you need to read.
This is just a suggestion of a possible protocol. You could also get rid of "Type".
So it would be something like:
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
int bytesToRead = messageByte[1];
while(!end)
{
bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length == bytesToRead )
{
end = true;
}
}
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
The following code compiles and looks better. It assumes the first two bytes providing the length arrive in binary format, in network endianship (big endian). No focus on different encoding types for the rest of the message.
import java.nio.ByteBuffer;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
class Test
{
public static void main(String[] args)
{
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
Socket clientSocket;
ServerSocket server;
server = new ServerSocket(30501, 100);
clientSocket = server.accept();
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2);
int bytesToRead = byteBuffer.getShort();
System.out.println("About to read " + bytesToRead + " octets");
//The following code shows in detail how to read from a TCP socket
while(!end)
{
bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length() == bytesToRead )
{
end = true;
}
}
//All the code in the loop can be replaced by these two lines
//in.readFully(messageByte, 0, bytesToRead);
//dataString = new String(messageByte, 0, bytesToRead);
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
You can read your BufferedInputStream like this. It will read data till it reaches end of stream which is indicated by -1.
inputS = new BufferedInputStream(inBS);
byte[] buffer = new byte[1024]; //If you handle larger data use a bigger buffer size
int read;
while((read = inputS.read(buffer)) != -1) {
System.out.println(read);
// Your code to handle the data
}
int c;
String raw = "";
do {
c = inputstream.read();
raw+=(char)c;
} while(inputstream.available()>0);
InputStream.available() shows the available bytes only after one byte is read, hence do .. while

Categories

Resources