I'm trying to make ftpclient which will use only sockets. I'm making a connection with server but I don't have idea how to display files. Here is my code:
package pl.edu.ftp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import pl.edu.config.ConfigData;
public class FTPProtocol {
private Socket socket;
private BufferedReader reader;
private OutputStreamWriter writer;
private Socket socket2;
private BufferedReader reader2;
private OutputStreamWriter writer2;
private String serverImportantOutput;
private boolean firstSocket = true;
public void makeConnection(ConfigData configData) throws UnknownHostException, IOException, InterruptedException {
socket = new Socket(configData.getServerAddress(), configData.getPort());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new OutputStreamWriter(socket.getOutputStream());
(new Thread(new Runnable() {
public void run() {
try {
String line;
if (firstSocket == true) {
while ((line = reader.readLine()) != null) {
System.out.println("SERVER: " + line);
if (line.startsWith("227 Entering Passive Mode")) {
serverImportantOutput = line;
}
}
} else {
while ((line = reader.readLine()) != null) {
System.out.println("SERVER: " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
})).start();
Thread.sleep(2000);
sendCommand("USER " + configData.getUsername());
sendCommand("PASS " + configData.getPassword());
sendCommand("SYST");
sendCommand("FEAT");
sendCommand("PWD");
sendCommand("TYPE I");
sendCommand("PWD");
List<String> newData = sendCommandPasv("PASV");
socket2 = new Socket(newData.get(0), Integer.parseInt(newData.get(1)));
reader2 = new BufferedReader(new InputStreamReader(socket2.getInputStream()));
writer2 = new OutputStreamWriter(socket2.getOutputStream());
sendCommand2("LIST");
}
private void sendCommand(String command) throws IOException, InterruptedException {
firstSocket = true;
writer.write(command + "\r\n");
writer.flush();
System.out.println("Client:" + command);
Thread.sleep(2000);
}
private void sendCommand2(String command) throws IOException, InterruptedException {
firstSocket = true;
writer2.write(command + "\r\n");
writer2.flush();
System.out.println("Client:" + command);
Thread.sleep(2000);
firstSocket = false;
Thread.sleep(2000);
}
private List<String> sendCommandPasv(String command) throws IOException, InterruptedException {
List<String> listOfStrings = new ArrayList<String>();
writer.write(command + "\r\n");
writer.flush();
System.out.println("Client:" + command);
Thread.sleep(2000);
String fullAdress = serverImportantOutput.substring(serverImportantOutput.indexOf("(") + 1,
serverImportantOutput.indexOf(")"));
List<String> partsOfAdress = Arrays.asList(fullAdress.replaceAll("\\s+", "").split(","));
String host = partsOfAdress.get(0) + "." + partsOfAdress.get(1) + "." + partsOfAdress.get(2) + "."
+ partsOfAdress.get(3);
String port = Integer
.toString(Integer.parseInt(partsOfAdress.get(4)) * 256 + Integer.parseInt(partsOfAdress.get(5)));
System.out.println("Host: " + host);
System.out.println("Port: " + port);
listOfStrings.add(host);
listOfStrings.add(port);
return listOfStrings;
}
}
I tried to use LIST, NLST, MLSD but still nothing work. In console I have:
SERVER: 227 Entering Passive Mode (127,0,0,1,197,183)
Host: 127.0.0.1
Port: 50615
Client:LIST
And "Client:LIST" I have to wait very long. After that I got:
SERVER: 421 Connection timed out.
Somebody have maybe any idea what I'm doing wrong?
I edited now this method:
private void sendCommand2(String command) throws IOException, InterruptedException {
writer.write(command + "\r\n");
writer.flush();
System.out.println("Client:" + command);
firstSocket = false;
Thread.sleep(2000);
}
And now as result I have:
SERVER: 227 Entering Passive Mode (127,0,0,1,196,72)
Host: 127.0.0.1
Port: 50248
Client:LIST
SERVER: 150 Opening data channel for directory listing of "/"
SERVER: 226 Successfully transferred "/"
But it still doesn't display any files.
Now I edited to read from reader2 when "bool firstSocket" is false. So it should read from "reader2" after sending "LIST" command, but it still display nothing.
(new Thread(new Runnable() {
public void run() {
try {
String line;
if (firstSocket == true) {
while ((line = reader.readLine()) != null) {
System.out.println("SERVER: " + line);
if (line.startsWith("227 Entering Passive Mode")) {
serverImportantOutput = line;
}
}
} else {
while ((line = reader2.readLine()) != null) {
System.out.println("SERVER: " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
})).start();
You can try to connect to the IP/port returned in the PASV response only after receiving 1xx response to the LIST command.
You have to send the LIST command to the (main) control connection, not to the data connection.
Read RFC 959 for details.
Related
import java.io.*;
import java.net.*;
public class WebServer{
private void run(){
try {
ServerSocket serverSocket = new ServerSocket(5520);
while(true){
try {
Socket serverClient = serverSocket.accept();
WebServerThread wst = new WebServerThread(serverClient);
wst.start();
} catch (IOException evt) {
System.out.println("Error");
}
}
} catch (IOException evt) {
System.out.println("error");
}
}
public static void main(String[] args) {
WebServer ws = new WebServer();
System.out.println("Server is up and running.");
ws.run();
}
}
import java.io.*;
import java.net.*;
import java.lang.*;
class WebServerThread extends Thread {
Socket serverClient;
BufferedReader in = null;
public WebServerThread(Socket clientSocket) {
serverClient = clientSocket;
}
public void run() {
try {
in = new BufferedReader(new InputStreamReader(serverClient.getInputStream()));
//System.out.println(in.readLine());
HTTP http = new HTTP(in.readLine(), serverClient);
in.close();
serverClient.close();
} catch (IOException e) {
System.out.println("Error");
} catch (NullPointerException e){
System.out.println("bad");
}
}
}
import java.io.*;
import java.nio.Buffer;
import java.util.StringTokenizer;
import java.net.*;
public class HTTP {
String contentTypeLine;
String file;
String version = "HTTP/1.1";
//String crlf = "\\r\\n";
String statusLine;
String responseHeader;
String statusCodePhrase;
String headerFieldName = "Content-type: ";
String headerValue;
String header;
public HTTP(String request, Socket socket) throws IOException {
StringTokenizer st = new StringTokenizer(request);
st.nextToken();
file = "." + st.nextToken();
try {
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
headerValue = contentType(file);
statusLine = "HTML/1.0 200 OK\r\n";
responseHeader = "Content-type: " + headerValue + "\r\n";
dos.writeBytes(statusLine);
dos.writeBytes(responseHeader);
dos.writeBytes("\r\n");
System.out.println(statusLine);
System.out.println(responseHeader);
System.out.println("Client requesting file: " + file);
writeEntityBody(file, bin, dos);
System.out.println("FIle: " + file + " sent successfully.");
} catch (FileNotFoundException evt) {
System.out.println(file + " not found.");
System.out.println("Requested file does not exist.");
statusCodePhrase = "404 Not Found";
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes("<HTML>" + "<HEAD><TITLE>Not Found</TITLE></HEAD>"
+ "<BODY>Not Found</BODY></HTML>");
} catch (IOException evt) {
System.out.println("Bad");
}
}
private void writeEntityBody(String file, BufferedInputStream bin, DataOutputStream dos) throws IOException {
int CHUNK_SIZE = 1024;
byte[] buffer = new byte[CHUNK_SIZE];
int len;
while ((len = bin.read(buffer)) != -1) {
dos.write(buffer, 0, len);
}
bin.close();
dos.flush();
dos.close();
}
private String contentType(String file){
String extension = file.split("\\.")[2];
if(extension.equals("htm") || extension.equals("html") || extension.equals("txt")){
contentTypeLine = "text/html";
}
else if(extension.equals("jpg") || extension.equals("gif") || extension.equals("png") || extension.equals("bmp") || extension.equals("pdf")) {
contentTypeLine = "image/bmp";
}
else{
return "application/octet-stream";
}
return contentTypeLine;
}
}
So basically, my server listens for a request from the client, which is the browser, so if I type "127.0.0.1:5520/test.txt" it connects to port 5520 and requests the file "test.txt".
In terms of listening for requests and starting threads, its fine. But in the HTTP class, when my program performs these lines:
headerValue = contentType(file);
statusLine = "HTML/1.0 200 OK\r\n";
responseHeader = "Content-type: " + headerValue + "\r\n";
dos.writeBytes(statusLine);
dos.writeBytes(responseHeader);
dos.writeBytes("\r\n");
That ideally should create the header and the browser should identify that. But the browser is just writing all of that as if it were part of the message body.
I've tried it on several different browsers and these were the results:
IE: Displays statusLine, responseHeader as if it were part of the message body and displays the contents of the file.
Firefox: Throws out statusLine, displays responseHeader as part of the message body and displays the content of the file.
Chrome: ERR_INVALID_HTTP_RESPONSE
I'm not sure why the browser can't identify the header.
Hint: the protocol is called "HTTP", not "HTML".
I'm writing a simple mail client that needs to do the following:
Establish a TCP connection with a mail server.
Send/receive messages to/from the mail server.
Close the connection with the mail server.
So far, my client will setup a connection just fine, but when it tries to send "HELO" + my InetAddress, the host says the domain name is invalid.
How do I resolve this so that I can send email via my mail client?
Here is my code:
package main;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class MailClient {
private static int port;
private static String mailServer;
private Socket sock;
private DataInputStream inputStream;
private DataOutputStream outputStream;
private BufferedReader br;
//private OutputStreamWriter osw;
private PrintWriter pw;
public MailClient(String mailServer, int port) {
this.mailServer = mailServer;
this.port = port;
}
// Establish TCP connection with mail server
public void setUpConnection() {
System.out.println("Setting up connection to server...\n");
try {
sock = new Socket(mailServer, port);
inputStream = new DataInputStream(sock.getInputStream());
outputStream = new DataOutputStream(sock.getOutputStream());
br = new BufferedReader(new InputStreamReader(inputStream));
pw = new PrintWriter(outputStream);
//osw = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
if(readResponse() == 220) {
System.out.println("Connection established!\n");
}
} catch (UnknownHostException e) {
System.err.println("Host name" + mailServer + " isn't recognized\n");
} catch (IOException e) {
System.err.println("I/O for host " + mailServer + " failed.\n");
}
}
// Dialogue with mail server using SMTP
public void sendMessage(String from, String to, String subject, String message) {
System.out.println("Sending message to server...\n");
try {
String response;
writeMsg("HELO " + InetAddress.getLocalHost().getHostName() + "\n");
readResponse();
writeMsg("MAIL FROM: " + from + "\n");
readResponse();
writeMsg("RCPT TO: " + to + "\n");
readResponse();
writeMsg("DATA\n");
readResponse();
writeMsg("From: " + from + "\n");
writeMsg("To: " + to + "\n");
writeMsg("Date: " + "\n");
writeMsg("Subject: " + subject + "\n");
writeMsg(message + "\n");
writeMsg("\n.\n");
readResponse();
writeMsg("QUIT");
readResponse();
System.out.println("Message sent!");
String responseFromServer;
while((responseFromServer = br.readLine()) != null) {
System.out.println("Server response: " + responseFromServer);
if(responseFromServer.indexOf("Ok") != -1) {
System.out.println("Ok recieved from mail server!");
break;
}
}
closeConnection();
} catch (IOException e) {
e.printStackTrace();
}
}
// Close TCP connection
private void closeConnection() {
System.out.println("Closing connection to server...");
try {
br.close();
pw.close();
inputStream.close();
outputStream.close();
sock.close();
System.out.println("Connection to mail server closed.");
}catch(IOException e) {
System.err.println(e);
}
}
private int readResponse() throws IOException {
String line = br.readLine();
System.out.println("Server Response:" + line + "\n");
line = line.substring(0, line.indexOf(" "));
return Integer.parseInt(line);
}
private void writeMsg(String message) {
pw.println(message);
pw.flush();
System.out.println("Message to server: " + message);
}
public static void main(String[] args) {
String emailAddress = "test#domain.edu";
String subject = "test";
String message = "hello world";
String test= "mailserver.edu";
MailClient mc = new MailClient(test, 587);
mc.setUpConnection();
mc.sendMessage("example#yahoo.com", emailAddress, subject, message);
}
}
The verbatim error I'm getting: 501 5.5.4 Invalid domain name
Its driving me nuts trying days to grind this problem.
I am writing a java server to work with an android application. They communicate text string and xml.
Currently simple socket communication seems fine, however it breaks down when I tried to use transformer instead of simple println.
Server code as below
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
public class javamultithreadedserver implements Runnable {
Socket csocket;
static int listenport = 6021;
public static final String endOfCom = "endofcom";
String connectionname;
public javamultithreadedserver(Socket csocket, String connectionname) {
this.csocket = csocket;
this.connectionname = connectionname;
}
public static void main(String[] args) throws Exception {
int listentoport = 0;
//System.out.println(args.length);
if (args.length == 1){
listentoport = Integer.parseInt(args[0]);
} else{
listentoport = listenport;
}
ServerSocket ssock = new ServerSocket(listentoport);
System.out.println("Listening at port " + listentoport);
while (true) {
Socket sock = ssock.accept();
System.out.println("Connected. from: " + sock.getInetAddress().getHostAddress() + " " + sock.getInetAddress().getHostName() + " port: " + sock.getPort() + " " + sock.getInetAddress().getCanonicalHostName());
new Thread(new javamultithreadedserver(sock, sock.getInetAddress().getHostAddress() + " " + sock.getInetAddress().getHostName() + " " + sock.getInetAddress().getCanonicalHostName())).start();
}
}
#Override
public void run() {
try {
PrintWriter out = new PrintWriter(csocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(csocket.getInputStream()));
PrintStream pstream = new PrintStream (csocket.getOutputStream(), true);
String inputLine, outputLine;
System.out.println(connectionname + ": listening for query information.");
while ((inputLine = in.readLine()) != null) {
System.out.println(connectionname + ": " + inputLine);
//out.write("received something");
DBQuery q = new DBQuery(inputLine + DBQuery.regexsplit + "connectionname" + DBQuery.regexsplit + connectionname);
DOMSource dmsource = q.returns();
***//StreamResult consoleResult = new StreamResult(System.out); //debug***
StreamResult consoleResult = new StreamResult(pstream);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Thread.sleep(100);
***transformer.transform(dmsource, consoleResult);***
//out.println("println this is a testprogram"); // client receive ok
pstream.flush();
System.out.println(connectionname + ": reply sent.");
if (inputLine == endOfCom){
System.out.println(connectionname + ": is satisfied and terminated communication.");
break;
}
}
pstream.close();
csocket.close();
}catch (IOException e) {
System.out.println(e);
}catch (Exception e) {
System.out.println(e);
}
}
}
And the android client code as below:
public void run() {
if (barcode.length() > 0) {
Socket socket = null;
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
socket.setSoTimeout(10000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.write(barcode + ENDL);
if(out.checkError()){
showToUI("PrintWriter had error");
} else {
showToUI("Query sent");
}
int i = 0;
while (true) {
try{
if (**(serverResponse = in.readLine()) != null**) {
if(serverResponse == endOfCom){
Log.i("communicated all data", "bye");
out.write(endOfCom + ENDL);
break;
} else{
}
Log.i("server says", serverResponse);
}
//Log.i("server says", (serverResponse == null? "null" :serverResponse ));
}catch(SocketTimeoutException e){
showToUI(barcode + ": Server did not respond in time");
if (i++ > 2) {
break;
}
}
}
} catch (final UnknownHostException e1) {
showToUI(e1.toString());
} catch (final IOException e1) {
showToUI(e1.toString());
} finally{
try {
socket.close();
} catch (IOException e) {
showToUI(e.toString());
}
}
}else{
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Please enter something in barcode", Toast.LENGTH_SHORT).show();
}
});
}
}
I have tested that the xml result returned was ok, if the Stream Result was set to System.out instead of the PrintStream pstream, everything prints perfectly to the console.
However with or without pstream.flush(), client received no response at (serverResponse = in.readLine()) != null.
Also the PrintWriter out which was based on the same Socket socket of pstream successfully gave feedback to the client. When out.println("println this is a testprogram"); was called, the client received log at the Log.i("server says", serverResponse); line OK.
One thing to note is that the reply is usually quite long, can be up to 65536 characters or even more, I do not know if that has any implication, I have tried to create a Buffered reader on the android app larger than the replying xml, it still did not work. The machines are communicating on local network, java server program is running on a different machine from the android emulator.
Any help is appreciated, this had been going on for days and nowhere.
readLine() won't return null until the peer closes the connection. And when it does return null, you need to break out of the loop. And don't compare string s with ==.
I"m working on a Client-Server chat program for a university project and I have little programming background. I've made 3 classes: ChatClient, ChatServer and ChatServerThread. I can currently have multiple clients connected and talking to the server at any time.
Although one of the requirements that I'm having the most difficulty is this: "Any message typed from 1 client is sent to all other clients" and also "Both sent and received messages should be displayed".
I've spent the last few nights just trying to get this extra bit of functionality working but have had no luck.
I've been reading and looking around for a while but I have lots of difficulty adapting online examples to my work. I've read that I should be creating a list of sockets and then iterate through the list and send data to everyone in the list, which makes sense in my head but gives me a headache when I try implementing it. Any help with this would be very greatly appreciated. Extra points if anyone can give me some insight on how I could encrypt the sent data.
ChatClient
import java.net.*;
import java.io.*;
public class ChatClient {
private Socket socket = null;
private DataInputStream console = null;
private DataOutputStream streamOut = null;
private String myName = null;
private BufferedReader StreamIn = null;
private String response = null;
public ChatClient(String serverName, int serverPort) {
try {
console = new DataInputStream(System.in);
System.out.println("What is your name?");
myName = console.readLine();
System.out.println(myName + " <" + InetAddress.getLocalHost() + "> ");
} catch (IOException ioe) {
System.out.println("Unexpected exception: " + ioe.getMessage());
}
System.out.println("Establishing connection. Please wait ...");
try {
socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
StreamIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
streamOut = new DataOutputStream(socket.getOutputStream());
streamOut.writeUTF(":" + myName + " <" + InetAddress.getLocalHost() + "> HAS JOINED");
streamOut.flush();
} catch (UnknownHostException uhe) {
System.out.println("Host unknown: " + uhe.getMessage());
} catch (IOException ioe) {
System.out.println("Unexpected exception: " + ioe.getMessage());
}
String line = "";
while (!line.equals(".bye")) {
try {
line = console.readLine();
streamOut.writeUTF(myName + " <" + InetAddress.getLocalHost() + "> : " + line);
streamOut.flush();
} catch (IOException ioe) {
System.out.println("Sending error: " + ioe.getMessage());
}
}
}
public void stop() {
try {
if (console != null) console.close();
if (streamOut != null) streamOut.close();
if (socket != null) socket.close();
} catch (IOException ioe) {
System.out.println("Error closing ...");
}
}
public static void main(String args[]) {
ChatClient client = null;
if (args.length != 2)
System.out.println("Usage: java ChatClient host port");
else
client = new ChatClient(args[0], Integer.parseInt(args[1]));
}
}
ChatServer
import java.net.*;
import java.io.*;
import java.util.*;
public class ChatServer implements Runnable {
private ServerSocket server = null;
private Thread thread = null;
private ChatServerThread client = null;
private String clientSentence = null;
private int peers = 0;
private List clients = new ArrayList();
final List sockets = new ArrayList();
public ChatServer(int port) {
try {
System.out.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
start();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
public void run() {
while (thread != null) {
try {
System.out.println("Waiting for a client ...");
addThread(server.accept());
} catch (IOException ie) {
System.out.println("Acceptance Error: " + ie);
}
}
}
public void addThread(Socket socket) {
System.out.println("Client accepted: " + socket);
client = new ChatServerThread(this, socket);
try {
client.open();
client.start();
} catch (IOException ioe) {
System.out.println("Error opening thread: " + ioe);
}
}
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void stop() {
if (thread != null) {
thread.stop();
thread = null;
}
}
public void increment(String sentence) {
peers++;
String[] info = sentence.split(" ");
String name = info[0].replace(":", "");
System.out.println(name + " Has joined the room, we now have " + peers + " peer(s).");
clients.add(name);
}
public Boolean isAllowed(String name, Socket socket) {
try {
String stringSearch = name;
BufferedReader bf = new BufferedReader(new FileReader("allowed.txt"));
int linecount = 0;
String line = "";
System.out.println("Searching for " + stringSearch + " in file...");
while ((line = bf.readLine()) != null) {
linecount++;
String[] words = line.split(" ");
for (String word : words) {
if (word.equals(stringSearch)) {
System.out.println("User is allowed");
registerSocket(socket);
return true;
}
}
}
bf.close();
} catch (IOException e) {
System.out.println("IO Error Occurred: " + e.toString());
}
System.out.println("User is not allowed");
return false;
}
public void showAll() {
for (int i = 0; i < clients.size(); i++) {
System.out.print(clients.get(i));
}
}
public void registerSocket(Socket socket) {
//socket = new DataOutputStream(socket.getOutputStream());
sockets.add(socket);
for (int i = 0; i < sockets.size(); i++) {
System.out.println(sockets.get(i));
}
}
public static void main(String args[]) {
ChatServer server = null;
if (args.length != 1)
System.out.println("Usage: java ChatServer port");
else
server = new ChatServer(Integer.parseInt(args[0]));
}
}
ChatServerThread
import java.net.*;
import java.io.*;
public class ChatServerThread extends Thread {
private Socket socket = null;
private ChatServer server = null;
private int ID = -1;
private DataInputStream streamIn = null;
private String clientSentence = null;
public String newGuy = null;
DataOutputStream streamOut = null;
public ChatServerThread(ChatServer _server, Socket _socket) {
server = _server;
socket = _socket;
ID = socket.getPort();
}
public void run() {
System.out.println("Server Thread " + ID + " running.");
while (true) {
try {
String sentence = streamIn.readUTF();
//System.out.println(sentence);
char c = sentence.charAt(0);
String[] command = null;
command = sentence.split(" ");
String name = command[0].substring(1);
System.out.println("Sending out: " + sentence + " via ");
streamOut.writeBytes(sentence);
if (c == ':') {
if (server.isAllowed(name, socket))
server.increment(sentence);
else {
close();
}
}
} catch (IOException ioe) {
}
}
}
public void open() throws IOException {
streamIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}
public void close() throws IOException {
if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
}
}
I run my java webserver on port 6799
My directory has a txt.txt file and pdf.pdf file
When I give localhost:6799/txt.txt, it gives perfect output saying
GET /txt.txt HTTP/1.1HTTP/1.0 200 OK
Content-type: text/plain
This is a very simple text file
But when I give localhost:6799/pdf.pdf from browser, it gives java.lang.NullPointerException
This is my code
import java.net.*;
public final class WebServer {
public static void main(String args[]) throws Exception {
int port = 6799;
System.out.println("\nListening on port " + port);
ServerSocket listen = new ServerSocket(port);
while (true) {
Socket socket = listen.accept();
HttpRequest request = new HttpRequest(socket);
Thread thread = new Thread(request);
thread.start();
}
}
}
--
import java.io.*;
import java.net.*;
import java.util.StringTokenizer;
public final class HttpRequest implements Runnable {
final String CRLF = "\r\n";
Socket socket;
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
#Override
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private void processRequest() throws Exception {
BufferedReader br;
DataOutputStream dos;
try (InputStream is = socket.getInputStream()) {
br = new BufferedReader(new InputStreamReader(is));
String requestline = br.readLine();
System.out.println("\n" + requestline);
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes(requestline);
StringTokenizer tokens = new StringTokenizer(requestline);
tokens.nextToken(); // skip over the method, which should be "GET"
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.0 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
//contentTypeLine = "Content-type: " + "text/html" + CRLF;
entityBody = "<HTML>"
+ "<HEAD><TITLE>Not Found</TITLE></HEAD>"
+ "<BODY>Not Found</BODY></HTML>";
}
dos.writeBytes(statusLine);
dos.writeBytes(contentTypeLine);
dos.writeBytes(CRLF);
if (fileExists) {
sendBytes(fis, dos);
fis.close();
} else {
dos.writeBytes(entityBody);
}
}
br.close();
dos.close();
socket.close();
}
private void sendBytes(FileInputStream fis, DataOutputStream dos) throws IOException {
byte[] buffer = new byte[4096];
int bytes = 0;
while ((bytes = fis.read(buffer)) != -1) {
dos.write(buffer, 0, bytes);
}
}
private String contentType(String fileName) {
if (fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
return "image/jpeg";
}
if (fileName.endsWith(".gif")) {
return "image/gif";
}
if (fileName.endsWith(".txt")) {
return "text/plain";
}
if (fileName.endsWith(".pdf")) {
return "application/pdf";
}
return "application/octet-stream";
}
}
STACK TRACE
java.lang.NullPointerException
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:274)
at HttpRequest.processRequest(HttpRequest.java:65)
at HttpRequest.run(HttpRequest.java:20)
at java.lang.Thread.run(Thread.java:724)
At least one issue is this code:
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
BufferedReader will return null at the end of the stream, so calling .length() on a null object will yield a NullPointerException.
A more idiomatic way to write this is:
while ((headerLine = br.readLine()) != null && headerLine.length() != 0) {
System.out.println(headerLine);
}
...which takes advantage of short-circuit logic to not evaluate the second condition if the result of (headerLine = br.readLine()) is null.
It is happening because for some reason you have toggled comment on the following line:
//contentTypeLine = "Content-type: " + "text/html" + CRLF;
Untoggle it and you're good!