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.
Related
I try to make my own proxy server and already implemented the http support for my proxy server. The proxy server works fine.
Now I want to have https as well (only with sockets). I looked up what I have to do at https://www.rfc-editor.org/rfc/rfc2817.
In my function I try to establish a TLS tunnel.
With my approach I only get a method not allowed as response. I also check some source in the internet, but didn't find anything which can help me with my problem.
Here is my function.
private Socket openTLSTunnel(String host) throws IOException {
String raw_request = "CONNECT " + host + ":80 HTTP/1.1\n"
+ "Host: " + host + ":80"
+ "\r\n\r\n";
// Make a connection to the website.
Socket tunnel = new Socket();
int timeout = 10000;
var server = new InetSocketAddress(host, 80);
tunnel.connect(server, timeout);
// Write the request to server.
OutputStream out = tunnel.getOutputStream();
byte[] msg = raw_request.getBytes(StandardCharsets.UTF_8);
out.write(msg);
out.flush();
// TODO send error to client.
// Get the response from server.
InputStream in = tunnel.getInputStream();
byte reply[] = new byte[200];
int replyLen = 0;
int newlinesSeen = 0;
boolean headerDone = false;
while (newlinesSeen < 2) {
int i = in.read();
if (i < 0) {
throw new IOException("Unexpected EOF from proxy");
}
if (i == '\n') {
headerDone = true;
++newlinesSeen;
}
else if (i != '\r') {
newlinesSeen = 0;
if (!headerDone && replyLen < reply.length) {
reply[replyLen++] = (byte) i;
}
}
}
String replyStr = new String(reply, 0, replyLen, "ASCII7");
// Check if connection established.
if(!replyStr.toLowerCase().contains("200 connection established")) {
System.out.println("No TLS connection established!");
throw new AccessDeniedException(replyStr);
}
else{
System.out.println("Connection established!");
}
return tunnel;
}
Thanks in advance!
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
So I'm trying to create an smtp from scratch, (assignment) and I'm trying to connect classes together but miserably failing and trying everything out. The compiler doesn't throw up any errors but when I run it I don't get very far. I tried calling the other classes with the .start thread but still, failure
If you could help me or give tips, I would really appreciate it
//Problem seems to be here: I have no idea how to correct it
socketManager soketManager = null;
DataInputStream clientDataIn = new DataInputStream(soketManager.getInputStream());
socketManager clientReaderSocket = soketManager;```
public class socketManager {
public Socket soc = null;`
`
//socketManager.java
public DataInputStream input = null;
public DataOutputStream output = null;
public socketManager(Socket socket) throws IOException {
soc = socket;
input = new DataInputStream(soc.getInputStream());
output = new DataOutputStream(soc.getOutputStream());
}
public InputStream getInputStream() throws IOException {
input = new DataInputStream(soc.getInputStream());
return null;
}
public OutputStream getOutputStream() throws IOException {
output = new DataOutputStream(soc.getOutputStream());
return null;
}
}
Exception in thread "Thread-1" java.lang.NullPointerException at
me.censored.loopback.SMTPclient.Client$ClientSocketManager.run(Client.java:117)
at java.base/java.lang.Thread.run(Thread.java:834)
// Main Method:- called when running the class file.
public static void main(String[] args) throws UnknownHostException, IOException {
Port Declaration & Checks.
String serverIP = "loopback";
int defaultServerPort = 25;
PortManager portManage = new PortManager();
Thread portManagerThread = new Thread(portManage);
portManagerThread.start();
}// End of main
static public class PortManager implements Runnable {
Scanner userInput = new Scanner(System.in);
int serverPort = 25;
// Will accept only tcp/udp ports as of (2019) After several attempts the port
// will be auto selected to default 25,
// Should we accept parsed HEX?
boolean portCompletion = false;
short portTriesCounter = 1;
public void run() {
try {
do {
// Asks user for server's port at the start up of the client.
System.out.println("Please enter the port the server is on.");
String userEntry = userInput.nextLine();
userInput.close();
try {
serverPort = Integer.parseInt(userEntry);
if (portTriesCounter != 5) { // Partial tries timeout.
if (serverPort != 0) { // "Port Zero" does not officially exist. It is defined as an invalid
// port
// number. But valid Internet packets can be formed and sent "over
// the
// wire"
// to and from "port 0" just as with any other ports.
if ((serverPort > 0 && serverPort <= 1023)
|| (serverPort >= 1024 && serverPort <= 49151)
|| (serverPort >= 49152 && serverPort <= 65535)) // Check for ports inside the
// tcp/udp
// range
portCompletion = true;
else {
System.out.println(
"Wrong input! Make sure you are using correct numbers and port range! ");
portCompletion = false;
portTriesCounter++;
}
// End Check for ports inside the tcp/udp range
} else {
System.out.print("Wrong input! ");
portCompletion = false;
portTriesCounter++;
}
// End Check for zero
}
// End Too many attempts
else {
portTriesCounter = 5;
portCompletion = true;
System.out.print("Many wrong attemps. Selecting and trying the default port (25)... ");
try {
System.out.print("Success");
portCompletion = true;
serverPort = 25; // For SSL connections use port 465.
} catch (Exception except) {
portCompletion = false;
}
}
} catch (Exception except) {
portCompletion = false;
portTriesCounter++;
} finally {
userInput.close();
}
} while (!portCompletion);
ClientSocketManager clientSocketManage = new ClientSocketManager();
Thread clientSocketManagerThread = new Thread(clientSocketManage);
clientSocketManagerThread.start();
System.out.println("DEBUG 0");
} catch (Exception except) { // Any Failure will send 421 Error to client
System.out.println("\t 421 \t Service not available, closing transmission channel.\n" + except);
}
}
}
static class ClientSocketManager implements Runnable {
public void run() {
try {
String CRLF = "\r\n";
String LF = "\n";
boolean SocketInitiation = false;
socketManager soketManager = null;
DataInputStream clientDataIn = new DataInputStream(soketManager.getInputStream());
socketManager clientReaderSocket = soketManager;
DataOutputStream clientDataOut;
clientDataOut = new DataOutputStream(soketManager.getOutputStream());
String sendSocketMessage = (CRLF);
clientDataOut.writeUTF(sendSocketMessage);// Sends string to output stream using UTF-8
clientDataOut.flush();
System.out.println("DEBUG 1");
String socketReplyIn = clientDataIn.readUTF();
PortManager portInstance = new PortManager();
int portNumber = portInstance.serverPort;
Socket soket = new Socket("loopback", portNumber);
ClientWriter clientWrite = new ClientWriter(soket);
Thread clientWriteThread = new Thread(clientWrite);
ClientReader clientRead = new ClientReader(soket);
Thread clientReadThread = new Thread(clientRead);
System.out.println("DEBUG 2");
// Cleans stream from any write buffer method.
System.out.println("Connection to server using TCP...");
if (socketReplyIn.contains("220")) {
System.out.println("\t 220 \t Service ready"); // Connection established successfully
clientReadThread.start();
clientWriteThread.start();
SocketInitiation = true;
} else {
System.out.println("\t 421 \t Service not available, closing transmission channel");
SocketInitiation = false;
}
} catch (IOException e) {
System.out.println("\t 421 \t Service not available, closing transmission channel");
System.out.println("TCP connection error: " + e);
}
}
}
you have defined socketManager soketManager = null; in ClientSocketManager.
but you never assigned a value to it, so it is still null.
The code after that is trying to access streams from it, which is throwing NullPointerException:
DataInputStream clientDataIn = new DataInputStream(soketManager.getInputStream());
socketManager clientReaderSocket = soketManager;
DataOutputStream clientDataOut;
clientDataOut = new DataOutputStream(soketManager.getOutputStream());
String sendSocketMessage = (CRLF);
clientDataOut.writeUTF(sendSocketMessage);// Sends string to output stream using UTF-8
clientDataOut.flush();
System.out.println("DEBUG 1");
just create a new instance of the socketManager and assign it to soketManager before using it.
PortManager portInstance = new PortManager();
int portNumber = portInstance.serverPort;
Socket soket = new Socket("loopback", portNumber);
socketManager soketManager = new sockerManager(soket);
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;
}
I ran into an issue trying to read from a DataOutputStream with a Scanner. The following code fails with an input mismatch exception.
DataOutputStream o = new DataOutputStream(new FileOutputStream("temp"));
o.writeByte(1);
o.flush(); o.close();
Scanner i = new Scanner(new FileInputStream("temp"));
System.out.println(i.nextByte());
i.close();
So what output streams ARE compatible with Scanner? And is there an Output/Input stream pair that are built for reading and writing all the primitive types and string lines? I really wanted a non-deprecated readLine() method, and all the input streams I've seen that have that method are deprecated.
EDIT:
The input and output streams will be across sockets for a Client/Server application. Here is the entire relevant code for each side:
SERVER
package server;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Scanner;
/**
* Server class handles all clients that wish to read a file stored on this
* server's
* database. Also connects to other servers to share some information.
*
* #author Josh Wilkins
*/
public class Server{
//Server message type constants
private static final byte REPLY = 0;
private static final byte YES = 1;
private static final byte NO = 2;
private static final byte UPDATE = 3;
private final int id;
private final ServerSocket fileServer; //connection point for clients
private HashMap<String, FileObject> files; //list of files in database, hashed by file name
/**
* Creates a new file server with given id on the specified port.
* <p>
* #param id
* #param port
* <p>
* #throws IOException
*/
public Server(int id, int port) throws IOException{
this.id = id;
fileServer = new ServerSocket(port);
files = new HashMap<>();
}
/**
* Loops forever, accepting new clients and creating threads to handle
* them.
* <p>
* #throws IOException
*/
public void acceptClients() throws IOException{
while( true ){
Socket client = fileServer.accept();
(new ClientHandler(client)).run();
}
}
/**
* Sends most updated version of specified file to specified server. Will
* only send update if the server should host the file. UNIMPLEMENTED.
* <p>
* #throws UnsupportedOperationException
*/
private void sendUpdate(int server, FileObject file){
//TODO
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* Creates a new file in the database with the file name contained in the
* string file.
* <p>
* #param file the file name of the new file object
*/
private synchronized void createFileObject(String file){
//TODO: Reject files not hashed to this server
try{
files.put(file, new FileObject(file));
} catch(IOException ex){
System.err.println("Failed to create file: " + file);
ex.printStackTrace(System.err);
}
}
/**
* Determines if this server is allowed to initiate a write request for a
* file by giving the client the most current version number.
* <p>
* #param file the file name of the file in question
* <p>
* #return true if allowed to initiate, false otherwise
*/
private boolean canInitiate(String file){
int hash0 = file.hashCode() % 7;
int hash1 = (file.hashCode() + 1) % 7;
return id == hash0 || id == hash1;
}
/**
* Threaded class to handle all requests from a single client connection.
*/
class ClientHandler extends Thread{
//Client message type constants
private static final byte READ = 0;
private static final byte WRITE = 1;
private static final byte COMMIT = 2;
private static final byte ABORT = 3;
private Socket client;
private DataOutputStream out;
private Scanner in;
private HashMap<String, Integer> pendingUpdates;
/**
* Sets up data input and output streams from given client socket.
* <p>
* #param client the socket that this client is connected to
*/
public ClientHandler(Socket client) throws IOException{
this.client = client;
out = new DataOutputStream(client.getOutputStream());
in = new Scanner(client.getInputStream());
pendingUpdates = new HashMap<>();
}
/**
* Listens for messages coming from client until the connection is
* closed on the client side.
*/
#Override
public void run(){
//Loops until the client closes the connection, then hasNext returns false
while( in.hasNext() ){
//wait for the next message type to be written to the stream
byte msgType = in.nextByte();
switch( msgType ){
case READ:
parseRead();
break;
case WRITE:
parseWrite();
break;
case COMMIT:
parseCommit();
break;
case ABORT:
parseAbort();
break;
default:
}
}
//connection is no longer needed, try to clean everything up
try{
in.close();
out.close();
client.close();
} catch(IOException ex){
System.err.println("Failed to close client at " + client.getInetAddress());
ex.printStackTrace(System.err);
}
}
/**
* Parses read message from client by collecting data from the input
* stream and processing it. Assumes the message type byte has already
* been read. If the file exists in the database, its contents are
* written to the client, otherwise a null string is written.
*/
private void parseRead(){
//TODO: Reject files not hashed to this server
String file = in.nextLine().trim(); //get requested file name (should end with \n)
String contents = "";
if( files.containsKey(file) ){
try{
contents = files.get(file).getContents();
} catch(IOException ex){
System.err.println("Error reading from file: " + file);
ex.printStackTrace(System.err);
}
} else {
//TODO: Need to decide how to handle no such file
// - create file and return empty
// - just return empty, but don't create
// - return some error indicator (change file to "-1" or "File Not Found")
contents = "";
}
//send REPLY message to client
sendReply(file, contents);
}
/**
* Parses write message from client by collecting data form the input
* stream and processing it. Assumes the message type byte has already
* been read. If the file does not exist, one is created immediately
* regardless of further success. If the version number is viable, or
* if this server can initiate a write for the given file, the update is
* queued with the respective FileObject. The client is sent a YES or
* NO answer depending on success of queueing the update.
*/
private void parseWrite(){
//TODO: Reject files not hashed to this server
int version = in.nextInt(); //get version first
String file = in.nextLine().trim(); //get file name
String contents = in.useDelimiter("\\Z").next(); //read entire remaining stream for contents
boolean queued = false;
//Create file if it does not exist yet.
if( !files.containsKey(file) ){
createFileObject(file);
}
//queue update to file object
try{
//only queue if version is given or if this server can initiate
if( version > 0 ){
queued = files.get(file).queueUpdate(contents, version);
} else if( version < 0 && canInitiate(file) ){
queued = files.get(file).queueUpdate(contents);
version = files.get(file).getVersion() + 1;
}
} catch(IOException ex){
System.err.println("Failed to queue update to: " + file);
ex.printStackTrace(System.err);
}
//send response to client (positive if queued, negative if not)
if( queued ){
//TODO: What happens if an update is already queued?
pendingUpdates.put(file, version);
sendYes(version, file);
} else {
sendNo(file);
}
}
/**
* Parses commit message from client by collecting data form the input
* stream and processing it. Assumes the message type byte has already
* been read. If valid server id is read from the stream, an update
* message is sent to that server for the file. No response is sent to
* client.
*/
private void parseCommit(){
//TODO: Reject files not hashed to this server
int failed = in.nextInt();
String file = in.nextLine().trim();
//TODO: Handle improper commit (no pending update)
int version = pendingUpdates.remove(file);
try{
files.get(file).commitUpdate(version);
} catch(IOException ex){
System.err.println("Failed to commit: " + file + " v. " + version);
ex.printStackTrace(System.err);
}
if( failed >= 0 ){
sendUpdate(failed, files.get(file));
}
}
/**
* Parses abort message from client by collecting data form the input
* stream and processing it. Assumes the message type byte has already
* been read. Simply removes the pending update from the queues. No
* response is sent to the client.
*/
private void parseAbort(){
//TODO: Reject files not hashed to this server
String file = in.nextLine().trim();
int version = pendingUpdates.remove(file); //if no update is queued this simply returns null
//what happens if:
// Integer xObj = null;
// int x = xObj;
// print(x);
try{
files.get(file).abortUpdate(version);
} catch(IOException ex){
System.err.println("Failed to abort: " + file + " v. " + version);
ex.printStackTrace(System.err);
}
}
/**
* Sends reply message to client. Assumes partial failure is impossible.
* <p>
* #param file name of file
* #param contents data contained in file
*/
public void sendReply(String file, String contents){
try{
out.writeByte(REPLY);
out.writeChars(file + "\n"); //end file name with CR for easy reading
out.writeChars(contents);
} catch(IOException ex){
System.err.println("Error sending REPLY(" + file + ", <" + contents.length() + ">)");
ex.printStackTrace(System.err);
}
}
/**
* Sends yes message to client. Assumes partial failure is impossible.
* <p>
* #param version this updates version number
* #param file name of file
*/
public void sendYes(int version, String file){
try{
out.writeByte(YES);
out.writeInt(version);
out.writeChars(file + "\n");
} catch(IOException ex){
System.err.println("Error sending YES(" + version + ", " + file + ")");
ex.printStackTrace(System.err);
}
}
/**
* Sends reply message to client. Assumes partial failure is impossible.
* <p>
* #param file name of file
*/
public void sendNo(String file){
try{
out.writeByte(NO);
out.writeChars(file + "\n");
} catch(IOException ex){
System.err.println("Error sending NO(" + file + ")");
ex.printStackTrace(System.err);
}
}
}
}
CLIENT
import java.io.*;
import java.net.Socket;
import java.util.Random;
import java.util.Scanner;
/**
* Client will take as input the operations (WRITE or READ), the file it wishes to use,
* and the servers in the network. The client will attempted to connect to three servers
* when a WRITE is chosen and a random server for READ. The servers ranges for READ and WRITE
* are based on a hashed value of the file name + the next in the line.
* example: Sever 1 , Server 2 and Server 3;
*
* #author kattex
*/
public class Client {
private Socket socket = null;
private Scanner inputStream = null;
private DataOutputStream outputStream = null;
private boolean isConnected = false;
private int sequenceNumber = -1;
private int response = 0;
private byte READ = 0;
private byte WRITE = 1;
private byte COMMIT = 2;
private byte ABORT = 3;
private byte YES = 1;
private byte NO = 2;
private byte REPLY = 0;
/**
* Connect with server code running in local host or in any other host
*/
private void connect(String address, int port) {
try {
// socket = new Socket("localHost", 4445);
System.out.println(address + " " + port);
socket = new Socket(address, port);
//outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new Scanner(socket.getInputStream());
isConnected = true;
} catch (IOException e) {
System.out.println("Unable to connect to server " + address);
}
}
/*
* Create a random integer within a min and max range
*/
public static int randInt(int min, int max, int count) {
Random rand = new Random();
System.out.println("randInt: " + min + "," + max + "," + count);
int randomNum = rand.nextInt((max - min) + 1) + min;
if (randomNum > count){
randomNum = randomNum % count;
if (randomNum < 0){
randomNum += count;
}
}
System.out.println("Random value: " + randomNum);
return randomNum;
}
/*
* Generate hash value for server numbers
*/
public static int hashFileName(String fileName, int serverCount){
int number = fileName.hashCode() % serverCount;
if (number < 0){
number += serverCount;
}
System.out.println("Hash Number: " + number);
return number;
}
/*
* Write out the contents to a file, if the file does not exist create it
*/
public static void CreateFile(String filename, String content){
try {
File file = new File(filename);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
System.out.println("Done");
} catch (IOException e) {
System.out.println("Erro creating file");
e.printStackTrace();
}
}
/*
* Find the next server in the list
*/
public static int nextServer(int number, int count){
int nextInt;
number++;
nextInt = number % count;
if (number < 0){
number += count;
}
return nextInt;
}
/*
* Send the WRITE messaget to server
*/
private void sendWrite(String obj){
try {
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
outputStream.writeByte(WRITE);
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
outputStream.writeInt(sequenceNumber);
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
outputStream.writeChars(obj);
outputStream.writeChar('\n');
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
String contents = readFile(obj);
System.out.println("Contents of file " + obj);
outputStream.writeChars(contents);
System.out.print("Pause...");
(new Scanner(System.in)).nextLine();
System.out.println("sending message to server");
int msgType = inputStream.nextByte();
if (msgType == YES){
sequenceNumber = inputStream.nextInt();
String tempFileName = inputStream.nextLine().trim();
response = 1;
System.out.println("Receved YES for file " + tempFileName);
}
if (msgType == NO){
String tempFileName = inputStream.nextLine();
System.out.println("Receved NO for file " + tempFileName);
}
} catch (IOException e) {
System.out.println("Error writing WRITE message to server");
e.printStackTrace(System.err);
}
}
/*
* Read the file into a string that can be sent throught a TCP socket
*/
public String readFile(String fileName) throws FileNotFoundException{
String output = new Scanner(new File(fileName)).useDelimiter("\\Z").next();
System.out.println("File output in READFile" + output);
return output;
}
/*
* Send Abort message to the server
*/
public void sendAbort(String obj){
try {
outputStream.writeByte(ABORT);
outputStream.writeChars(obj);
outputStream.writeChar('\n');
System.out.println("sending abort message to server");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error sending ABORT message to server");
}
}
/*
* Send commit to Server
*/
public void sendCommit(int Fsvr, String obj){
try {
outputStream.writeByte(COMMIT);
outputStream.writeInt(Fsvr);
outputStream.writeBytes(obj);
System.out.println("sending Commit message to server");
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error sending COMMIT message to server");
}
}
/*
* Send READ request
*/
public void sendREAD(String obj){
String u;
try {
outputStream.writeByte(READ);
outputStream.writeChars(obj);
outputStream.writeChar('n');
System.out.println("sending READ Request message to server");
byte type = inputStream.nextByte();
//File fl = new File(obj);
if (type == REPLY){
String file = inputStream.nextLine().trim();
String contents = inputStream.useDelimiter("\\z").next();
CreateFile(file, contents);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("Erorro sedning READ Request message to server");
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Client client = new Client();
int serverCount = 0;
int FSvr = -1;
int length = args.length;
String Object = "j.txt";
String type = "write";
int hashValue = hashFileName(Object, 7);
if (type.equals("write") ){
Client client2 = new Client();
Client client3 = new Client();
client.connect("localhost", 4445);
if (client.isConnected){
client.sendWrite(Object);
if (client.response == 1){
client2.sequenceNumber = client.sequenceNumber;
}
}
int nextValue = nextServer(hashValue,7);
//need to add commit message
int thirdValue = 3;
System.out.println("Server Numbers " + hashValue + " " + nextValue + " " + thirdValue);
serverCount = client.response + client2.response + client3.response;
System.out.println("Servercount " + serverCount);
if (serverCount >= 2){
if(client.response != 1 ){FSvr = hashValue; }
if(client2.response != 1){FSvr = nextValue; }
if(client3.response != 1){FSvr = thridValue;}
if(client.response == 1){client.sendCommit( FSvr,Object);}
if(client2.response == 1){client2.sendCommit(FSvr,Object);}
if(client3.response == 1){client3.sendCommit(FSvr,Object);}
}else{
if(client.response == 1 ){client.sendAbort(Object); }
if(client2.response == 1){client2.sendAbort(Object);}
if(client3.response == 1){client3.sendAbort(Object);}
}
} else {
if (type.equals("read")){
int RValue = randInt(hashValue, hashValue + 2, 7);
System.out.println("HashVlue: " + hashValue + " RValue: " + RValue);
client.sendREAD(Object);
}
}
}
}
Most of the message handling on the server side is in ClientHandler. I'm less familiar with the client side, as I didn't write it. Obviously with this implementation, there is an InputMismatchException when reading the byte msgType on the server side. I also realized while searching for the solution, that at the very least I should be adding white space between all the fields for Scanner to parse them separately, but I still have issues.
Use a DataOutputStream and a DataInputStream. Instead of lines, use writeUTF() and readUTF(). For efficiency, put buffered streams underneath, and flush the output before you read.
Scanner takes Input Streams such as System.in you are better off using BufferedReader here. E.g
BufferedReader reader = new BufferReader(new FileReader("temp"));
System.out.println(reader.readLine());
reader.close();
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.