How to keep TCP sockets open? - java

Our application has a ping-pong like conversation with many servers (each server has a corresponding thread where those connections are made). Code below works, but it opens a new connection for every new request and is used only once, which soon leads to reaching max connection cap set by server.
DataProvider.java
public static ZnResult sendTcpQuery(String xml, String url, int port) {
List<ZnXmlResult> results = new ArrayList<>();
String xmlString = xml != null ? new String((xml + "\n").getBytes()) : "";
int error = ZnResult.OK;
try (Socket clientSocket = new Socket(url, port)) {
clientSocket.setSoTimeout(CONNECTION_TIMEOUT);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
try (BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"))) {
outToServer.writeBytes(xmlString);
try (StringWriter responseFromServer = new StringWriter()) {
String readLine;
while ((readLine = inFromServer.readLine()) != null) {
...
}
}
outToServer.close();
clientSocket.close();
}
} catch (Exception ex) {
LOG.error("Exception {}", url + ":" + port, ex);
error = ZnResult.ERR;
}
return error == ZnResult.OK ? new ZnResult(results) : new ZnResult(error);
}
How can I transform it, so everything can be done within one connection?
I figured I would do something like this:
SocketFactory.java
public class SocketFactory {
private static HashMap<String, Socket> socketsByAddress = new HashMap<>();
private static HashMap<Socket, DataOutputStream> outputStreamsBySocket = new HashMap<>();
private static HashMap<Socket, BufferedReader> readersBySocket = new HashMap<>();
public static Socket getSocket(String address) {
String ip = Tools.getIpFromAddress(address);
int port = Tools.getPortFromAddress(address);
Socket socket = socketsByAddress.get(address);
if (socket == null) {
try {
socket = new Socket(ip, port);
socket.setSoTimeout(60000);
socketsByAddress.put(address, socket);
} catch (IOException ex) {
Logger.getLogger(SocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return socket;
}
public static DataOutputStream getOutputStream(Socket socket) {
DataOutputStream outputStream = outputStreamsBySocket.get(socket);
if (outputStream == null) {
try {
outputStream = new DataOutputStream(socket.getOutputStream());
outputStreamsBySocket.put(socket, outputStream);
} catch (IOException ex) {
Logger.getLogger(SocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return outputStream;
}
public static BufferedReader getReader(Socket socket) {
BufferedReader reader = readersBySocket.get(socket);
if (reader == null) {
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
readersBySocket.put(socket, reader);
} catch (IOException ex) {
Logger.getLogger(SocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return reader;
}
}
DataProvider.java
public static ZnResult sendTcpQuery(String xml, String url, int port) {
List<ZnXmlResult> results = new ArrayList<>();
int error = ZnResult.OK;
try {
String xmlString = xml != null ? new String((xml + "\n").getBytes()) : "";
Socket clientSocket = SocketFactory.getSocket(url + ":" + port);
DataOutputStream outToServer = SocketFactory.getOutputStream(clientSocket);
BufferedReader inFromServer = SocketFactory.getReader(clientSocket);
outToServer.writeBytes(xmlString);
try (StringWriter responseFromServer = new StringWriter()) {
String readLine;
while ((readLine = inFromServer.readLine()) != null) {
...
}
}
} catch (Exception ex) {
LOG.error("Exception {}", url + ":" + port, ex);
error = ZnResult.ERR;
}
return error == ZnResult.OK ? new ZnResult(results) : new ZnResult(error);
}
but it just doesn't work and only the first one go through.

This loop reads until the end of the stream.
while ((readLine = inFromServer.readLine()) != null) {
A stream only ends once. i.e. you can't end the stream but later use it again.
What you need to do instead;
have a terminating line which can't occur in your data. e.g. wait for "[EOF]"
send the length of data first and read only that much data.

Try to initiate the Socket object using URL rather than IP address as you were doing in your first code and see if it works for you.

Related

Sent file with socket in java

I want to send file from client to server using socket.
But at the server, I only receive the first line. What is the problem?
Server Code
public static void main(String ars[]){
int port = 1000;
try {
ServerSocket sercoc = new ServerSocket(port);
System.out.println("dkjd");
while (true){
Socket soc = sercoc.accept();
InputStream flux = soc.getInputStream();
BufferedReader entree = new BufferedReader(new InputStreamReader(flux));
String message = entree.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Client Code
public static void main(String args[]){
String hote = "127.00.0.1";
int port = 1000;
FileReader input = null;
File file = new File("src/view/files/temperature2.txt");
Socket soc = null;
try {
soc = new Socket(hote,port);
OutputStream flux = soc.getOutputStream();
OutputStreamWriter sortie = new OutputStreamWriter(flux);
try {
input = new FileReader("src/view/files/temperature2.txt");
char c;
while ((c = (char) input.read()) != -1){
sortie.write(c);
//sortie.write("\n");
}
} finally {
if (input != null){
input.close();
}
}
sortie.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
If I use BufferedReader I found errors and I can't receive anything!
in my code I have implemented the transfer of photo, txt and zip files through ObjectOutputStream and ObjectInputStream.
code:
// output
ObjectOutputStream objectOutput = new ObjectOutputStream(connection.clientSocket.getOutputStream());
objectOutput.writeObject(your_file);
// input
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
buffer = (byte[]) ois.readObject();

Android Client Socket IOException

EDIT: The problem is the input in the Client.class so when the Android devices receives an answer from the Server. Those are the following lines that causes the crash:
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String text;
while ((text = reader.readLine()) != null) {
Log.d("ClientLog", "Received from Server"+ text);
}
Here is my Client.class in Android:
public class Client implements Runnable{
public Client() {
}
#Override
public void run() {
try {
Log.d("ClientLog", "Socket creation incoming");
Socket client = new Socket("localhost", 5555);
Log.d("ClientLog", "Client has been started");
// Streams:
OutputStream out = client.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
// -----------------------------------------------------------------------
writer.write("Test");
writer.newLine();
writer.flush();
String text;
while ((text = reader.readLine()) != null) {
Log.d("ClientLog", "Received from Server"+ text);
}
writer.close();
reader.close();
} catch (UnknownHostException e) {
Log.d("ClientLog", "Error: Host not found");
e.printStackTrace();
} catch (IOException e) {
Log.d("ClientLog", "Error: IOException");
e.printStackTrace();
}
}
}
And if needed my Server.class in Java:
public class Server {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(30);
ServerSocket server;
try {
server = new ServerSocket(5555);
System.out.println("Server has been started on Port 5555");
while(true) {
try {
Socket client = server.accept();
//Thread t = new Thread(new Handler(client));
//t.start();
executor.execute(new Handler(client));
} catch (IOException e) {
System.out.println("Error IOExceotion");
e.printStackTrace();
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
The Handler.class needed for Server.class:
public class Handler implements Runnable{
private Socket client;
public Handler(Socket pClient) {
client = pClient;
}
#Override
public void run() {
try {
// Streams:
OutputStream out = client.getOutputStream();
PrintWriter writer = new PrintWriter(out);
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
// -----------------------------------------------------------------------
String text = null;
while ((text = reader.readLine()) != null) {
writer.write(text+ "\n");
writer.flush();
System.out.println("Recieved from Client: "+ text);
}
//Close Streams
writer.close();
reader.close();
client.close();
} catch (IOException e) {
System.out.println("Error IOException");
e.printStackTrace();
}
}
}
The debugging was resolved in the comments above.
Step 1: Add permissions to the android manifest file as was outlined here: Java socket IOException - permission denied
Step 2: Change the while ((text = reader.readLine()) != null) check. I guess the text = reader.readLine() != null check was problematic.

Multithreading with client server program

I am trying to implement multi threading with a client/server program I have been working on. I need to allow multiple clients to connect to the server at the same time. I currently have 4 classes: a Client, a Server, a Protocol and a Worker to handle the threads. The following code is what I have for those classes:
SocketServer Class:
public class SocketServer {
public static void main(String[] args) throws IOException {
int portNumber = 9987;
try (
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
Thread thread = new Thread(new ClientWorker(clientSocket));
thread.start(); //start thread
String inputLine, outputLine;
// Initiate conversation with client
Protocol prot = new Protocol();
outputLine = prot.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = prot.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("quit"))
break;
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
SocketClient Class:
public class SocketClient {
public static void main(String[] args) throws IOException
{
String hostName = "localhost";
int portNumber = 9987;
try (
Socket socket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("quit"))
break;
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
Protocol Class:
public class Protocol {
private static final int waiting = 0;
private static final int sentPrompt = 1;
private int status = waiting;
public String processInput(String theInput) {
String theOutput = null;
if (status == waiting) {
theOutput = "Please enter what you would like to retrieve: 'customer' or 'product' ";
status = sentPrompt;
}
else if ( status == sentPrompt ) {
if ( theInput.equalsIgnoreCase("product")) {
File f = new File("product.txt");
Scanner sc = null;
try {
sc = new Scanner(f);
} catch (FileNotFoundException ex) {
Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
}
while ( sc.hasNextLine() ) {
String line = sc.nextLine();
theOutput = "The current product entries are : " + line;
}
return theOutput;
}
else if ( theInput.equalsIgnoreCase("customer")) {
File f = new File("customer.txt");
Scanner sc = null;
try {
sc = new Scanner(f);
} catch (FileNotFoundException ex) {
Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
}
while ( sc.hasNextLine() ) {
String line = sc.nextLine();
theOutput = "The current customer entries are : " + line;
}
return theOutput;
}
else if ( theInput.equalsIgnoreCase("quit")) {
return "quit";
}
else {
return "quit";
}
}
return theOutput;
}
}
The ClientWorker Class:
public class ClientWorker implements Runnable {
private final Socket client;
public ClientWorker( Socket client ) {
this.client = client;
}
#Override
public void run() {
String line;
BufferedReader in = null;
PrintWriter out = null;
try {
System.out.println("Thread started with name:"+Thread.currentThread().getName());
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("in or out failed");
System.exit(-1);
}
while (true) {
try {
System.out.println("Thread running with name:"+Thread.currentThread().getName());
line = in.readLine();
//Send data back to client
out.println(line);
//Append data to text area
} catch (IOException e) {
System.out.println("Read failed");
System.exit(-1);
}
}
}
}
When I run the server and client, everything works fine as expected. Then when I try to run another client, it just hangs there and does not prompt the client to give a response. Any insight into what I am missing is greatly appreciated!
Your server code should address implement below functionalities.
Keep accepting socket from ServerSocket in a while loop
Create new thread after accept() call by passing client socket i.e Socket
Do IO processing in client socket thread e.g ClientWorker in your case.
Have a look at this article
Your code should be
ServerSocket serverSocket = new ServerSocket(portNumber);
while(true){
try{
Socket clientSocket = serverSocket.accept();
Thread thread = new ClientWorker(clientSocket);
thread.start(); //start thread
}catch(Exception err){
err.printStackTrace();
}
}
How many times does serverSocket.accept() get called?
Once.
That's how many clients it will handle.
Subsequent clients trying to contact will not have anybody listening to receive them.
To handle more clients, you need to call serverSocket.accept() in a loop.

Java SocketException: Software caused connection abort

I'm trying to develop a client-server exchange program, and when I try to send data from client to server, I'm running into a SocketException. I've looked at other answers but none of them fit my exact case; I have two calls to osw.write, and only one of them works.
Client:
package me.primesearch.client;
import java.math.BigInteger;
import java.net.*;
import java.io.*;
public class PrimeSearchClient {
public static void main(String[] args) throws IOException{
Socket connection = null;
try{
/** Define a host server */
String host = "localhost";
/** Define a port */
int port = 25564;
StringBuffer instr = new StringBuffer();
System.out.println("SocketClient initialized");
/** Obtain an address object of the server */
InetAddress address = InetAddress.getByName(host);
/** Establish a socket connetion */
connection = new Socket(address, port);
/** Instantiate a BufferedOutputStream object */
BufferedOutputStream bos = new BufferedOutputStream(connection.
getOutputStream());
/** Instantiate a BufferedInputStream object for reading
/** Instantiate a BufferedInputStream object for reading
* incoming socket streams.
*/
BufferedInputStream bis = new BufferedInputStream(connection.
getInputStream());
/**Instantiate an InputStreamReader with the optional
* character encoding.
*/
InputStreamReader isr = new InputStreamReader(bis, "US-ASCII");
/**Read the socket's InputStream and append to a StringBuffer */
int c;
/** Instantiate an OutputStreamWriter object with the optional character
* encoding.
*/
OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
while(true){
String process = "drq " + (char) 13;
/** Write across the socket connection and flush the buffer */
osw.write(process);
osw.flush();
while ( (c = isr.read()) != 13)
instr.append( (char) c);
for(int i=0;i<50;i++){
BigInteger offset=new BigInteger(instr.toString()).add(BigInteger.valueOf(i));
if(isProbablyPrime(offset)){
process = "pri" + " " + offset + " " + (offset.divide(new BigInteger("50"))).toString() + (char) 13;
System.out.println(process);
/** Write across the socket connection and flush the buffer */
osw.write(process); //This doesn't work
osw.flush();
System.out.println("Prime found at " + offset);
}
}
}
} catch(IOException e) {
e.printStackTrace();
} finally {
connection.close();
}
}
public static boolean isProbablyPrime(BigInteger n) {
if(n.longValue()!=0){
BigInteger lessOne = n.subtract(BigInteger.ONE);
// get the next prime from one less than number and check with the number
return lessOne.nextProbablePrime().compareTo(n) == 0;
}
return false;
}
}
Server:
package me.primesearch.server;
import java.net.*;
import java.io.*;
public class PrimeSearchServer implements Runnable {
private Socket connection;
#SuppressWarnings("unused")
private int ID;
PrimeSearchServer(Socket s, int i) {
this.connection = s;
this.ID = i;
}
#SuppressWarnings("resource")
public static void main(String[] args) {
int port = 25564;
int count = 0;
try{
ServerSocket socket1 = new ServerSocket(port);
System.out.println("MultipleSocketServer Initialized");
while (true) {
Socket connection = socket1.accept();
Runnable runnable = new PrimeSearchServer(connection, ++count);
Thread thread = new Thread(runnable);
thread.start();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
BufferedInputStream is = new BufferedInputStream(connection.getInputStream());
InputStreamReader isr = new InputStreamReader(is);
int character;
StringBuffer process = new StringBuffer();
while((character = isr.read()) != 13) {
process.append((char)character);
}
System.out.println(process);
String returnCode="0";
if(process.toString().split(" ")[0].equals("drq")){
System.out.println("Job request recieved");
File file = new File("packages.txt");
//Process input
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
String prevLine="";
boolean i = false;
int count=0;
while ((line = br.readLine()) != null) {
System.out.println("Looking for a package to send");
// process the line.
if(line.equals("0")){
System.out.println("Sending package " + count);
returnCode = Integer.toString(count);
i = true;
break;
}
prevLine = line;
count++;
System.out.println("No packages found");
}
if(!i){
returnCode = prevLine;
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("packages.txt", true)))) {
System.out.println("Creating new package");
out.println("0");
returnCode=Integer.toString(count);
}catch (IOException e) {
e.printStackTrace();
}
}
}
} else if (process.toString().split(" ")[0].equals("pri")){
System.out.println("Prime request recieved");
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("primes.txt", true)))) {
out.println(Integer.parseInt(process.toString().split(" ")[1]));
}catch (IOException e) {
e.printStackTrace();
}
updateLine(Integer.parseInt(process.toString().split(" ")[2]));
}
BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII");
osw.write(returnCode + (char)13);
osw.flush();
process = new StringBuffer();
}
catch (Exception e) {
System.out.println(e);
}
finally {
try {
connection.close();
}
catch (IOException e){
e.printStackTrace();
}
}
}
private void updateLine(int lines) throws IOException {
String data="packages.txt";
BufferedReader file = new BufferedReader(new FileReader(data));
String input = "";
String line;
for(int i=0;i<lines;i++){
input+=file.readLine()+System.lineSeparator();
}
file.readLine();
while ((line = file.readLine()) != null)
input += line + System.lineSeparator();
FileOutputStream os = new FileOutputStream(data);
os.write(input.getBytes());
file.close();
os.close();
}
}
Sorry if the indenting on the code looks a bit strange, I'm not used to using stack overflow.
You are closing the socket in your server class:
finally {
try {
connection.close();
}
catch (IOException e){
e.printStackTrace();
}
}
I think this is the problem. This is the first message you're sending to the server.
Client
String process = "drq " + (char) 13;
osw.write(process);
osw.flush();
And since your server stops reading after it gets a 13 char it closes the connection after it reads the first message.
Server
while((character = isr.read()) != 13) {
process.append((char)character);
}
I was getting the same exception when running functional test using TestNG. For me it was a version issue. Uninstalling it and installing older version fixed my issue. Read the following post for information.
https://github.com/cbeust/testng-eclipse/issues/91

BufferedWriter does not flush

I have the following problem....
try
{
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()));
while(true)
{
String clientRequest = "";
String tempStr = clientInput.readLine();
while(tempStr != null && !tempStr.equals("null"))
{
System.out.println(tempStr);
clientRequest += tempStr + " ";
tempStr = clientInput.readLine();
}
//Parse Request
ArrayList<String> tokenArray = parseRequest(clientRequest);
Calendar c = Calendar.getInstance();
switch(tokenArray.get(0))
{
case "GET":
{
clientOutput.write("HTTP/1.1 200 OK\r\n");
clientOutput.write("Date: " + c.getDisplayName(0, Calendar.LONG, Locale.UK).toString() + "\r\n");
clientOutput.write("Server: Java HTTP Server v1.0\r\n");
clientOutput.flush();
break;
//Write File
}
default:
{
clientOutput.write("500\r\n");
clientOutput.flush();
}
}
}
}
Every thing works completely fine up-and-till the clientOutput.write("HTTP....... line,
the client just keeps waiting and waiting... i've attempted to flush after every sucsessive write and yet nothing..... BUT This is the weird part - if i write to and flush before the code enters the while-loop the the writes in the case "GET": works perfectly...... ie
The code does execute all the way to the
clientOutput.flush();
break;
//Write File
.
try
{
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()));
clientOutput.write("HTTP/1.1 200 OK\r\n");
clientOutput.flush();
while(true)
{
String clientRequest = "";
String tempStr = clientInput.readLine();
while(tempStr != null && !tempStr.equals("null"))
{
System.out.println(tempStr);
clientRequest += tempStr + " ";
tempStr = clientInput.readLine();
}
//Parse Request
ArrayList<String> tokenArray = parseRequest(clientRequest);
Calendar c = Calendar.getInstance();
switch(tokenArray.get(0))
{
case "GET":
{
clientOutput.write("HTTP/1.1 200 OK\r\n");
clientOutput.write("Date: " + c.getDisplayName(0, Calendar.LONG, Locale.UK).toString() + "\r\n");
clientOutput.write("Server: Java HTTP Server v1.0\r\n");
clientOutput.flush();
break;
//Write File
}
Here is the code for the client
Socket s = new Socket("localhost", 1337);
BufferedReader fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter toServer = new BufferedWriter(new PrintWriter(s.getOutputStream()));
toServer.write("GET index.html HTTP/1.1\r\n");
toServer.write("HOST: 127.0.0.1\r\n");
toServer.write("Connection: close\r\n");
toServer.write("\r\n");
toServer.write("null\r\n");
toServer.flush();
while(true)
{
String ss = fromServer.readLine();
if(ss != null && !ss.equals("null"))
System.out.println(ss);
}
Server Class: Strydom_A_201103578_P03
public class Strydom_A_201103578_P03
{
Thread[] threadArray = new Thread[5];
int ClientCount = 0;
public Strydom_A_201103578_P03() throws ClientSizeExceededException
{
ServerSocket httpServer = null;
try
{
httpServer = new ServerSocket(1337);
}
catch (IOException ex)
{
Logger.getLogger(Strydom_A_201103578_P03.class.getName()).log(Level.SEVERE, null, ex);
}
while(true)
{
try
{
//Wait for connection
Socket clientSocket = httpServer.accept();
if(ClientCount < 5)
{
threadArray[ClientCount] = new Thread(new clientHandler(clientSocket));
threadArray[ClientCount].start();
ClientCount++;
}
else
{
throw new ClientSizeExceededException();
}
}
catch(IOException ex)
{
}
finally
{
}
}
}
class clientHandler implements Runnable
{
Socket clientSocket;
public clientHandler(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
#Override
public void run()
{
BufferedReader clientInput = null;
BufferedWriter clientOutput = null;
try
{
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()));
clientOutput.write(" ");
clientOutput.flush();
while(true)
{
String clientRequest = "";
String tempStr = clientInput.readLine();
while(tempStr != null && !tempStr.equals("null"))
{
System.out.println(tempStr);
clientRequest += tempStr + " ";
tempStr = clientInput.readLine();
}
//Parse Request
ArrayList<String> tokenArray = parseRequest(clientRequest);
Calendar c = Calendar.getInstance();
switch(tokenArray.get(0))
{
case "GET":
{
clientOutput.write("HTTP/1.1 200 OK\r\n");
clientOutput.write("Date: " + c.getDisplayName(0, Calendar.LONG, Locale.UK).toString() + "\r\n");
clientOutput.write("Server: Java HTTP Server v1.0\r\n");
clientOutput.flush();
break;
//Write File
}
default:
{
clientOutput.write("500\r\n");
clientOutput.flush();
}
}
}
}
catch (IOException ex)
{
Logger.getLogger(Strydom_A_201103578_P03.class.getName()).log(Level.SEVERE, null, ex);
}
finally
{
try
{
clientInput.close();
clientOutput.close();
}
catch (IOException ex)
{
Logger.getLogger(Strydom_A_201103578_P03.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private ArrayList<String> parseRequest(String tempStr)
{
StringTokenizer httpTokens = new StringTokenizer(tempStr, " ");
ArrayList<String> tokens = new ArrayList<>();
while(httpTokens.hasMoreTokens())
tokens.add(httpTokens.nextToken());
return tokens;
}
}
public static void main(String[] args) throws ClientSizeExceededException
{
new Strydom_A_201103578_P03();
}
}
public class TestClient
{
public TestClient()
{
try
{
Socket s = new Socket("localhost", 1337);
BufferedReader fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter toServer = new BufferedWriter(new PrintWriter(s.getOutputStream()));
toServer.write("GET index.html HTTP/1.1\r\n");
toServer.write("HOST: 127.0.0.1\r\n");
toServer.write("Connection: close\r\n");
toServer.write("\r\n");
toServer.write("null\r\n");
toServer.flush();
while(true)
{
String ss = fromServer.readLine();
if(ss != null && !ss.equals("null"))
System.out.println(ss);
}
}
catch (UnknownHostException ex)
{
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex)
{
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args)
{
new TestClient();
}
}
Client Class: TestClient
Create a project( or 2) and run the files
The problem here is the PrintWriter. It swallows exceptions. Change it to an OutputStreamWriter. Then you will see any exception that is being swallowed. In general you should avoid PrintWriters and PrintOutputStreams over a network. They swallow exceptions that you need to know about.
You need to change your inner while loop to look for the end of the client's request:
while(tempStr != null && !tempStr.equals("null"))
to:
while(tempStr != null && !tempStr.equals("null") && !tempStr.equals(""))
The client won't disconnect (causing a null) after it sends a request. It will give you a blank line to indicate the end of its request.
Reason why returning the response header right away is working? Maybe the client just reads the 200 and (eventually) disconnects? So when you are reading the client's request, it ends and you get a null eventually.
EDIT:
So running your code, it works fine for me. Both the client and server are sending and receiving both requests and responses. However, the server never disconnects (the client includes a Connection: close header) and the client continues to block on readLine(). Unsurprisinly, when I include the write() and flush() immediately after setting up the connection on the server-side nothing changes except I see HTTP/1.1 200 OK twice on the client's end. Maybe all you need to do is close the clientSocket in a finally{} block at the end of your try/catch{}?
So for the futhering of my now ended suffering - here is what i finally did....
I changed both the server and the clients readers from BufferedReader/Writer to DataInputstream/OutputStream.... And it works perfectly now - ! Thanks to everyone
Aiden
Just do this and it will work..........
Add true as the 2nd parameter in the PrintWriter
clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream(), true));

Categories