Java client app freezes when sending object through sockets - java

i have this client/server application, and the client application sometimes completely freezes when i try send object via sockets
public Client client = new Client();
petriNetList = client.query(client.actionLoadPetriNetList, MainWindow.loginUsername);
here is the code of the client
public class Client {
public static Socket kkSocket = null;
public static PrintWriter out = null;
public static BufferedReader in = null;
public static BufferedReader stdIn = null;
public static OutputStream outputStream = null ;
public static ObjectOutputStream objectOutputStream = null ;
public static InputStream inputStream = null ;
public static ObjectInputStream objectInputStream = null ;
public String actionSavePetriNet = "SAVE PETRI NET START";
/*
* Save petri net to server
*
* #param action identifies query
* #param petriName name of the petri net
* #param username username
* #param xml content of the petri net
*
* #return int response form server
*/
public int query (String action,String petriName,String username,String xml) throws IOException {
int size ;
int result = 0;
connect();
if (action.equals(actionSavePetriNet)) {
out.println(action); // save petri net
out.println(petriName); //petri net name
out.println(username); //username
System.out.println("(Client:)" + xml);
objectOutputStream.writeObject(xml); //send object over the network
System.out.println("Dostali sme sa sem ?");
result = Integer.parseInt(in.readLine()); //read response from server
}
disconnect();
return result;
}
/*
* connect to server
* TODO: ADD hostname and port as parameter
*/
public static void connect() throws IOException {
try {
kkSocket = new Socket("osiris-PC", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: taranis.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: taranis.");
System.exit(1);
}
stdIn = new BufferedReader(new InputStreamReader(System.in));
outputStream = kkSocket.getOutputStream();
objectOutputStream = new ObjectOutputStream(outputStream);
inputStream = kkSocket.getInputStream();
objectInputStream = new ObjectInputStream(inputStream);
}
/*
* Disconnect from server
* close all input/output streams
*
*/
public static void disconnect() throws IOException {
out.close();
in.close();
stdIn.close();
objectOutputStream.close();
outputStream.close();
objectInputStream.close();
inputStream.close();
kkSocket.close();
}
}
and this is the code of server
public class PetriServer {
public static Protocol kkp = new Protocol();
public static InputStream inputStream = null ;
public static ObjectInputStream objectInputStream = null ;
public static OutputStream outputStream = null ;
public static ObjectOutputStream objectOutputStream = null ;
public static void main(String[] args) throws IOException, ClassNotFoundException {
kkp.loadUsers();
while(true) {
ServerSocket serverSocket = null;
inputStream = null ;
objectInputStream = null ;
outputStream = null ;
objectOutputStream = null ;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
inputStream = clientSocket.getInputStream();
objectInputStream = new ObjectInputStream(inputStream);
outputStream = clientSocket.getOutputStream();
objectOutputStream = new ObjectOutputStream(outputStream);
inputLine = in.readLine();
String inputLine;
if (inputLine.equals("SAVE PETRI NET START")) {
String petriName;
String username;
String xml ;
String input;
int result;
int size ;
petriName = in.readLine(); //read petri name
System.out.println("(Server): prijali sme poziadavok na ulozenie " + petriName );
username = in.readLine(); //read username
System.out.println("(Server): poziadavok ide od usera: " + username);
while(true) {
//this is the line where is occasionally freezes
xml = (String)objectInputStream.readObject(); //read object over the network
if (!xml.isEmpty()) break;
}
System.out.println("(Server):" + xml);
result = kkp.savePetrinet(username, petriName,xml); //save it to the file
out.println(result);
}
out.close();
in.close();
objectInputStream.close();
inputStream.close();
objectOutputStream.close();
outputStream.close();
clientSocket.close();
serverSocket.close();
}
}
}
Does anybody know what can be problem ?
cheers.

You have the Socket InputStream on the server attached to two different inputs, ObjectInputStream and BufferedReader. InputStreams are not intended to be used this way, and doing so can cause a lot of problems. BufferedReaders, by their nature, are going to be pulling more data off the InputStream than you are actually reading. If they happen to buffer data that makes up an object, then your subsequent attempt to read the object off the ObjectInputStream will block, because the data has already been removed.
You need to pick one method or the other to read data. If you need to be able to read both Strings and Objects off the Socket, then you will have to go to a byte-oriented mode of operation where you read the bytes off into a byte array, then process the byte array yourself to insure that you don't loose any data.
Edit based on #Dunes comment below
Seems your best bet is to stick entirely with ObjectInputStream and make use of its other methods that allow you to read arbitrary primitive types from the stream. And, if you don't mind the deprecated call, it even has a readLine method.

Related

Why is my message sent only once in Java socket server?

there is a server that is considered to server multiple clients at the same time.
So when clients connects, he is added to clients array. And when server gets the message, it is sent to all the clients.
It works perfectly when one client is connected, but when I have 2 clients at the same time, the message is sent only once, it doesn't work anymore after that. What's the problem?
Server
static DataInputStream inputStream;
static DataOutputStream outputStream;
static ServerSocket serverSocket;
static final int PORT = 3003;
static Socket someClient;
static List<Socket> clients = new ArrayList<>();
public Server()
{
start();
}
public static void main(String[] args) throws IOException
{
try{
serverSocket = new ServerSocket(PORT);
print("Server started on " + serverSocket.getInetAddress().getHostAddress());
while (true)
{
someClient = serverSocket.accept();
new Server();
}
} catch (Exception e){
e.printStackTrace();
}
}
#Override
public void run()
{
try{
clients.add(someClient);
print("Connected from " + someClient.getInetAddress().getHostAddress());
InputStream sin = someClient.getInputStream();
OutputStream sout = someClient.getOutputStream();
inputStream = new DataInputStream(sin);
outputStream = new DataOutputStream(sout);
String message;
while (true)
{
message = inputStream.readUTF();
print(message);
for (int i = 0; i < clients.size(); i++)
{
Socket client = clients.get(i);
OutputStream os = client.getOutputStream();
DataOutputStream oss = new DataOutputStream(os);
oss.writeUTF(message);
}
}
} catch (Exception e){
e.printStackTrace();
}
}
Client
socket = new Socket("0.0.0.0", 3003);
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
inputStream = new DataInputStream(sin);
outputStream = new DataOutputStream(sout);
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(key != null && key.length() == 16)
{
Date date = new Date();
String msg = ">> " + nickname + ": " + messageField.getText()+" | " + date.getHours()+":"+date.getMinutes()+"\n";
try {
outputStream.writeUTF(Encrypt.AESEncrypt(key, msg));
} catch (IOException e1) {
e1.printStackTrace();
}
messageField.setText("");
}
else if(key == null)
JOptionPane.showMessageDialog(J_Frame, "Your key field is empty");
else if(key.length() != 16)
JOptionPane.showMessageDialog(J_Frame, "Key's length should be 16 symbols");
}
});
while (true)
{
String message;
message = inputStream.readUTF();
append("\n" + Encrypt.AESDecrypt(key, message));
}
} catch (Exception e1) {
clear();
append(">> Unable to connect to the server.");
hideButtons();
}
Every time a client connects to your server, it replaces the previous connection:
while (true)
{
someClient = serverSocket.accept();
...
}
someClient is static:
static Socket someClient;
which means it is shared by all threads.
Also, access to it is not synchronized in any way, which means changes to its value are not guaranteed to be visible to other threads.
As Peter Lawrey pointed out in the comments, the streams also need to be non-static:
static DataInputStream inputStream;
static DataOutputStream outputStream;
actually, the fact that you are always reading from the "latest" inputStream may be the main cause of the behavior you are describing.
outputStream seems to be unused, so it might be best to remove it.
In addition to that, OutputStreams may need to be flushed in order to actually send data.

convert byte stream to string from socket in server side java

I serialized an object to bytes and send to the server side.
in the server side i got the byte stream but i want to print the object/string i got from the server in order to verify i got it well
server side:
CarServerSocket = new ServerSocket(4441);
System.out.println("Server is ready and waiting for connection from client..\n");
try {
while (true) {
carSocket = CarServerSocket.accept();
System.out.println("Server Connected");
final DataInputStream bytesIR = new DataInputStream(carSocket.getInputStream());
bytesIRLength = bytesIR.readInt();
while (bytesIRLength > 0) {
byte[] messageIn = new byte[bytesIRLength];
bytesIR.readFully(messageIn,0,messageIn.length);
bytesIR.readUTF();
}
}
}catch(EOFException e ){
System.out.println("\ngot all objects from client.\ndisconnecting server...");
CarServerSocket.close();
carSocket.close();
}
}
Cliend side - serialization
objectOut.writeObject(CarList[i]); // converting object to bytes.
objectOut.flush();
objectInBytes = byteOut.toByteArray();
System.out.println("Sending car object #"+i);
dOut.writeInt(objectInBytes.length); // getting object bytes size.
dOut.write(objectInBytes); // sending object in bytes.
I tired to use: toString(), readUTF()... but no luck.
can anyone please advise how i solve it?
Thank you.
You can try to read data from your InputStream with some kind of InputStreamReader, something like this :
CarServerSocket = new ServerSocket(4441);
System.out.println("Server is ready and waiting for connection from client..\n");
try {
while (true) {
carSocket = CarServerSocket.accept();
System.out.println("Server Connected");
StringBuilder yourData = new StringBuilder();
new BufferedReader(new InputStreamReader(carSocket.getInputStream()))
.lines().forEach(stringBuilder::append);
System.out.println(yourData.toString());
}catch(EOFException e ){
System.out.println("\ngot all objects from client.\ndisconnecting server...");
CarServerSocket.close();
carSocket.close();
}
}
objectOut.writeObject(CarList[i]); // converting object to bytes.
objectOut.flush();
objectInBytes = byteOut.toByteArray();
System.out.println("Sending car object #"+i);
dOut.writeInt(objectInBytes.length); // getting object bytes size.
dOut.write(objectInBytes); // sending object in bytes.
All this is completely pointless. It just wastes time and space. Just use ObjectOutputStream.writeObject() directly to the socket at the sender, and ObjectInputStream.readObject() directly from the socket at the receiver.
You need to use ObjectInputStream to deserialize objects. Ok, so your object is entirely contained in a datagram that you've already received. You just need to turn the data buffer into an ObjectInputStream. Coding from the hip, this would be something like ...
try( ByteArrayInputStream bais = new ByteArrayInputStream(messageIn);
ObjectInputStream ois = new ObjectInputStream(bais)) {
Object o = ois.readObject();
}
Edit: Here is some complete code showing this working.
public class ByteStream {
public static void main(String[] args) throws IOException {
Server server = new Server(4441);
new Thread(server).start();
Client client = new Client(4441);
new Thread(client).start();
}
}
class Client implements Runnable {
private final Socket socket;
Client(int port) throws UnknownHostException, IOException {
socket = new Socket("localhost", port);
}
#Override
public void run() {
MyObject send = new MyObject();
send.x = 10;
send.msg = "X = ";
try {
try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(send);
oos.flush();
byte[] objectInBytes = baos.toByteArray();
int length = objectInBytes.length;
System.out.println("Client: sending 'objectInBytes' length = " + length);
dos.writeInt(length);
dos.write(objectInBytes);
} finally {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Server implements Runnable {
private final ServerSocket serverSocket;
Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
#Override
public void run() {
try {
try (Socket socket = serverSocket.accept();
DataInputStream bytesIR = new DataInputStream(socket.getInputStream())) {
int length = bytesIR.readInt();
byte[] messageIn = new byte[length];
bytesIR.readFully(messageIn);
System.out.println("Server: got datagram length = " + length);
process(messageIn);
} finally {
serverSocket.close();
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
private void process(byte[] messageIn) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(messageIn);
ObjectInputStream ois = new ObjectInputStream(bais)) {
Object o = ois.readObject();
System.out.println(o.getClass() + ": " + o);
}
}
}
class MyObject implements Serializable {
private static final long serialVersionUID = -1478875967217194114L;
double x;
String msg;
public String toString() { return msg + x; }
}
And the output:
Client: sending 'objectInBytes' length = 75
Server: got datagram length = 75
class MyObject: X = 10.0

Exception in thread "main" java.net.SocketException: Connection reset -

I have created a simple Client/Server program where the client takes a file from command line arguments. The client then sends the file to the server, where it is compressed with GZIP and sent back to the client.
The server program when ran first is fine, and produces no errors but after running the client I get the error.
I am getting an error saying the connection is reset, and i've tried numerous different ports so i'm wondering if there is something wrong with my code or time at which i've closed the streams?
Any help would be greatly appreciated!
EDIT - Made changes to both programs.
Client:
import java.io.*;
import java.net.*;
//JZip Client
public class NetZip {
//Declaring private variables.
private Socket socket = null;
private static String fileName = null;
private File file = null;
private File newFile = null;
private DataInputStream fileIn = null;
private DataInputStream dataIn = null;
private DataOutputStream dataOut = null;
private DataOutputStream fileOut = null;
public static void main(String[] args) throws IOException {
try {
fileName = args[0];
}
catch (ArrayIndexOutOfBoundsException error) {
System.out.println("Please Enter a Filename!");
}
NetZip x = new NetZip();
x.toServer();
x.fromServer();
}
public void toServer() throws IOException{
while (true){
//Creating socket
socket = new Socket("localhost", 4567);
file = new File(fileName);
//Creating stream to read from file.
fileIn = new DataInputStream(
new BufferedInputStream(
new FileInputStream(
file)));
//Creating stream to write to socket.
dataOut = new DataOutputStream(
new BufferedOutputStream(
socket.getOutputStream()));
byte[] buffer = new byte[1024];
int len;
//While there is data to be read, write to socket.
while((len = fileIn.read(buffer)) != -1){
try{
System.out.println("Attempting to Write " + file
+ "to server.");
dataOut.write(buffer, 0, len);
}
catch(IOException e){
System.out.println("Cannot Write File!");
}
}
fileIn.close();
dataOut.flush();
dataOut.close();
}
}
//Read data from the serversocket, and write to new .gz file.
public void fromServer() throws IOException{
dataIn = new DataInputStream(
new BufferedInputStream(
socket.getInputStream()));
fileOut = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(
newFile)));
byte[] buffer = new byte[1024];
int len;
while((len = dataIn.read(buffer)) != -1){
try {
System.out.println("Attempting to retrieve file..");
fileOut.write(buffer, 0, len);
newFile = new File(file +".gz");
}
catch (IOException e ){
System.out.println("Cannot Recieve File");
}
}
dataIn.close();
fileOut.flush();
fileOut.close();
socket.close();
}
}
Server:
import java.io.*;
import java.net.*;
import java.util.zip.GZIPOutputStream;
//JZip Server
public class ZipServer {
private ServerSocket serverSock = null;
private Socket socket = null;
private DataOutputStream zipOut = null;
private DataInputStream dataIn = null;
public void zipOut() throws IOException {
//Creating server socket, and accepting from other sockets.
try{
serverSock = new ServerSocket(4567);
socket = serverSock.accept();
}
catch(IOException error){
System.out.println("Error! Cannot create socket on port");
}
//Reading Data from socket
dataIn = new DataInputStream(
new BufferedInputStream(
socket.getInputStream()));
//Creating output stream.
zipOut= new DataOutputStream(
new BufferedOutputStream(
new GZIPOutputStream(
socket.getOutputStream())));
byte[] buffer = new byte[1024];
int len;
//While there is data to be read, write to socket.
while((len = dataIn.read(buffer)) != -1){
System.out.println("Attempting to Compress " + dataIn
+ "and send to client");
zipOut.write(buffer, 0, len);
}
dataIn.close();
zipOut.flush();
zipOut.close();
serverSock.close();
socket.close();
}
public static void main(String[] args) throws IOException{
ZipServer run = new ZipServer();
run.zipOut();
}
}
Error Message:
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at java.io.DataInputStream.read(DataInputStream.java:100)
at ZipServer.<init>(ZipServer.java:38)
at ZipServer.main(ZipServer.java:49)
First, the error occurs because the client fails and ends before sending any data, so that
the connection is closed at the time the server wants to read.
The error occurs because you assign the File objects to unused local variables (did your compiler not warn?)
public File file = null;
public File newFile = null;
public static void main(String[] args) throws IOException {
try {
String fileName = args[0];
File file = new File(fileName);
File newFile = new File(file +".gz");
}
catch (ArrayIndexOutOfBoundsException error) {
System.out.println("Please Enter a Filename!");
}
but In your toServer method you use the class variable file as parameter for FileInputStream and this variable is null and this results in an error which ends the program.
Second, if you finished the writing to the outputstream, you should call
socket.shtdownOutput();
Otherwise, the server tries to read until a timeout occurs.
Problem is that server is not able to download apache maven.
So what you can do is just copy the apache maven folder and paste it in the wrapper folder inside the project.
It will manually download the apache maven, and it will definitely work.

Socket data does not appear to be getting through to client

I've written some serverside socket handling code and I'm concerned that potentially my packets are not always making it back to the client. I am logging all my events and in my log files it says I am sending the information. But the client is also logging events and in their logs they say they do not receive anything.
My code to send the data is as follows:
public void write(Packet packet) {
String data = packet.serialize();
log("Send=[" + data + "]", "Write"); // log to file
try {
_writer.write(data);
_writer.flush();
} catch (Exception ex) {
log(ex, "write");
}
}
Each socket is created on a new thread and I create my writers and readers immediately like so (in the public run method):
// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
.getOutputStream()));
_reader = new SocketReader(_socket);
SocketReader is just a wrapper class I created for listening for responses and has a public read method like so:
public String read() throws IOException, SocketTimeoutException {
_socket.setSoTimeout(_timeOut);
if(_reader == null)
_reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
// read from the stream
return new PacketDataInputStream(_reader).read();
}
The PacketDataInputStream wrapper class:
BufferedReader _reader = null;
public PacketDataInputStream(BufferedReader reader)
{
_reader = reader;
}
public String read() throws IOException, SocketException {
StringBuilder builder = new StringBuilder();
int c = 0;
while((c = _reader.read()) != -1)
{
char ch = (char)c;
builder.append(ch);
if(ch == PacketConstants.ETX)
break;
}
if(builder.length() > 0)
return builder.toString();
else
return null;
}
The way I'm creating the actual socket listener objects is pretty standard I think:
InetAddress address = InetAddress.getByName(IP);
server = new ServerSocket( port, 0, address);
// My own manager class to handle all the sockets connected
WebSocketManager manager = new WebSocketManager(this);
Socket connection = null;
while(bContinue)
{
connection = server.accept();
if(bContinue) {
// assign the socket to a new thread and start
// that thread
manager.newSocket(connection);
} else {
connection.close();
}
}
Is is possible that I'm using the wrong objects for sending the data back.
Should I even be using a bufferedwriter and reader? I had thought that these were the best way to go but now I'm not so sure.
It's important to note that this does not happen all the time, just sporadically. It could be the clients code having bugs but I need to make sure that I'm doing it correctly before going back to them.
This code is run on a Linux Ubuntu server. Logging occurs to a text file, nothing special there. My log files show the Send="" data going back to the client and no exception so it appears as if the .write and .flush() worked? Socket connections are persistant and only closed by the client and or network issues.
UPDATE ----- Client Side code -------:
I did manage to get some of the client side code for how they are handling the send and receiving of data (just in case it's more obvious on their end). The client is actually connecting to this server via an Android device (if that helps).
Creation of socket
static final int BUFFER_SIZE = 20000; // Maximum packet size
java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
Sending:
try {
// Send the packet:
OutputStream stream = socket.getOutputStream();
stream.write(p.getByteArray ());
stream.flush();
// Update the time:
lastPacketSendTime = new Date ();
} catch (IOException e) {
setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
return false;
}
Receiving:
socket.setSoTimeout(timeout);
// Get the reader:
inputStream = socket.getInputStream();
while (true) {
// Get the next character:
int value = inputStream.read();
// Check for -1, indicating that the socket is closed:
if (value == -1) {
// The socket is closed remotely, so close it locally as well:
disconnect();
inputStream = null;
return null;
}
// ... and a bunch of other stuff to handle the actual data
}
EDIT 14-Nov:
This is actually proving to be more of a problem now. Both the client logs and the server logs appear to be sending. But at times the data doesn't appear to come through or if it does it is sometimes coming through 10 - 30 - 60 second delayed.
I can provide more information if required.
When you use BufferedReaders and BufferedWriters things get buffered. How about using the input and output streams directly.. Also, writers are character based, I don't know if you need to send binary data but if so that will be a problem with writers.
I am not sure whether this will be to your any use or not.. but i am giving you the code i used for client server communication..
Client Side:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server Code:
import java.io.*
import java.net.*;
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}

Printwriter not writing to outputStream

I'm trying to implement a basic web server in Java. When I direct a web browser to 127.0.0.1:8020/webpage.html, the server receives the request header, but when it tries to send the webpage back it doesn't show up on the browser.
Can anyone help?
public class WebServer
{
public static void main(String[] args)
{
try
{
ExecutorService scheduler = Executors.newCachedThreadPool();
ServerSocket server = new ServerSocket(8020);
while (true)
{
Socket client = server.accept();
Runnable r = new HTTPThread(client.getInputStream(), client.getOutputStream());
scheduler.execute(r);
System.out.println("LOG: New Thread Created");
}
}
catch (IOException e)
{
System.out.println("ERROR: Cannot listen on socket");
e.printStackTrace();
}
}
}
public class HTTPThread implements Runnable {
InputStream in;
OutputStream out;
private String fileName;
private String fileLoc;
private static final String rootLoc = "C:\\Users\\myName\\workspace\\HTTPServer\\src\\";
HTTPThread(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
public void run() {
try {
// show request headers and store http header
System.out.println("LOG: Preparing to read request");
String header = readInput(in);
System.out.println("LOG: Request read successfully!");
System.out.println(header);
// get file name from request header
fileLoc = rootLoc + header.substring(5, header.indexOf("H") - 1);
System.out.println(fileLoc);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(out));
//send response header and body
writer.print("HTTP/1.0 200 OK\nContent-Type: text/html\n\n" + fileReader(fileLoc));
System.out.println("LOG: Response Sent");
out.close();
in.close();
}
catch (IOException e) {
System.out.println("ERROR: Could not listen on socket");
System.exit(-1);
}
}
//Returns content of webpage as a string (html)
public String fileReader(String file) {
StringBuilder text = new StringBuilder();
String NL = System.getProperty("line.separator");
Scanner scanner;
try {
scanner = new Scanner(new FileInputStream(file));
while (scanner.hasNextLine()) {
text.append(scanner.nextLine() + NL);
}
return text.toString();
} catch (FileNotFoundException e) {
System.out.println("ERROR: File Not Found");
System.exit(-1);
return null;
}
}
//Reads bytestream from client and returns a string
private String readInput(InputStream is) {
BufferedReader in = new BufferedReader(new InputStreamReader(is));
try
{
String current;
String header = "";
while (!(current = in.readLine()).isEmpty())
{
header += current + System.getProperty("line.separator");
}
return header;
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
Adding writer.close(); before out.close(); would fix it.
http responses have a very specific format. the protocol is very specific about which characters separate the header from the content. you have the wrong characters.
as a side note, never use PrintWriter on top of a network stream as it hides IOExceptions (in general, avoid PrintWriter).

Categories

Resources