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).
Related
I am writing a web server from the scratch. There I need a Http codec which can decode a string request (buffer) to an Http object and encode http object into Sting (buffer).
I found three Codecs,
Apache Codecs (can't use this because this is tightly coupled with their server coding structure)
Netty Codes (can't use this because this is tightly coupled with their server coding structure)
JDrupes Codecs (Has some concurrency issues)
But non of these can be used for my purpose. Are there any other Codecs I can use?
class SimpleHttpsServer implements Runnable {
Thread process = new Thread(this);
private static int port = 3030;
private String returnMessage;
private ServerSocket ssocket;
/************************************************************************************/
SimpleHttpsServer() {
try {
ssocket = new ServerSocket(port);
System.out.println("port " + port + " Opend");
process.start();
} catch (IOException e) {
System.out.println("port " + port + " not opened due to " + e);
System.exit(1);
}
}
/**********************************************************************************/
public void run() {
if (ssocket == null)
return;
while (true) {
Socket csocket = null;
try {
csocket = ssocket.accept();
System.out.println("New Connection accepted");
} catch (IOException e) {
System.out.println("Accept failed: " + port + ", " + e);
System.exit(1);
}
try {
DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(csocket.getInputStream()));
PrintStream printStream = new PrintStream(new BufferedOutputStream(csocket.getOutputStream(), 1024),
false);
this.returnMessage = "";
InputStream inputStream = csocket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// code to read and print headers
String headerLine = null;
while ((headerLine = bufferedReader.readLine()).length() != 0) {
System.out.println(headerLine);
}
// code to read the post payload data
StringBuilder payload = new StringBuilder();
while (bufferedReader.ready()) {
payload.append((char) bufferedReader.read());
}
System.out.println("payload.toString().length() " + payload.toString().length());
if (payload.toString().length() != 1 || payload.toString().length() != 0) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(payload.toString());
// Handle here your string data and make responce
// returnMessage this can store your responce message
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + this.returnMessage;
printStream.write(httpResponse.getBytes("UTF-8"));
printStream.flush();
}else {
/*String httpResponse = "HTTP/1.1 200 OK\r\n\r\n";
outStream.write(httpResponse.getBytes("UTF-8"));
outStream.flush();*/
}
printStream.close();
dataInputStream.close();
// csocket.close();
System.out.println("client disconnected");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/************************************************************************************/
public static void main(String[] args) {
new SimpleHttpsServer();
}
}
may be this one is help you
I am writing a server-client program. It is like a simple console chat room. I use server thread to handle multiple clients. It works well if I put the Scanner inside the client constructor.(This part is commented) But, I want to move the Scanner part which requests input from user to the main. I got socket close error.I don't know what the problem is. How can I use send function to send data in main?
Client:
public class GameClient {
private Socket socket;
private String serverIP;
private OutputStreamWriter writer;
private BufferedReader reader;
public GameClient(String host){
this.serverIP = host;
try{
//Connect to server
socket = new Socket(InetAddress.getByName(serverIP), 1234);
writer = new OutputStreamWriter(this.socket.getOutputStream(), "UTF-8");
reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream(), "UTF-8"));
//Start a new thread for reading from server
new Thread(new GameClientReader(socket)).start();
Scanner scanner = new Scanner(System.in);
System.out.println("Write something: ");
String str = "";
// while((str = scanner.nextLine()) != null){
// writer.write(str);
// writer.write('\n');
// writer.flush();
// System.out.println("Write something: ");
// }
}catch(IOException e){
System.out.println("Client failed to connect!");
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void send(JSONObject json){
try{
String message = json.toJSONString();
writer.write(message);
writer.write('\n');
writer.flush();
}catch(IOException e){
e.printStackTrace();
}
}
public void send(String msg){
try {
writer.write(msg);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
GameClient client = new GameClient("127.0.0.1");
Scanner scanner = new Scanner(System.in);
System.out.println("Write something: ");
String str = "";
while((str = scanner.nextLine()) != null){
client.send(str);
System.out.println("Write something: ");
}
}
}
You close Socket in finally block of GameClient constructor, and then call method send which calls writer.write(msg); that uses instance of Socket
so i've been making a simple chat, than has a server and a bunch of clients connected to them. On the client side i have class ConnectionManager to manage creating socket and such. Here is it's core method:
public class ConnectionManager {
private Socket socket;
private BufferedReader reader;
private PrintWriter writer;
public ConnectionManager(String URL, int port){
tryConnectToServer(URL, port);
}
public BufferedReader getReader() {
return reader;
}
public PrintWriter getWriter() {
return writer;
}
private void tryConnectToServer(String ip, int servSocket) {
try{
socket = new Socket(ip, servSocket);
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
}
catch (IOException ex){
System.out.println("Unable to connect to specified server. Code pink");
ex.printStackTrace();
}
}
Connection Manager object is a part of ChatGUI. ChatGUI's fields writer and reader are obtained and set from CM in order to pass writer along with ChatGUI's JTextField (msgInput) to SendButtonListener:
private void addSendButton() {
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonActionListener(writer, msgInput));
panel.add(sendButton);
panel.add(this.msgArea);
}
Then, actionPerformed method does:
public class SendButtonActionListener implements ActionListener{
private PrintWriter writer;
private JTextField msgInput;
public SendButtonActionListener(PrintWriter pr, JTextField mi){
writer = pr;
msgInput = mi;
}
public void actionPerformed(ActionEvent event){
writer.println(msgInput.getText());
System.out.println("Sending: " + msgInput.getText());
flushMessageInputField();
}
private void flushMessageInputField(){
msgInput.setText("");
}
}
On the server side on the other hand i've got this:
try{
this.servSocket = new ServerSocket(port);
System.out.println("Server socket established");
}
catch (IOException ex){
System.out.println("Unable to establish server socket. Code pink \n");
ex.printStackTrace();
}
And after the above comes this:
public void waitForClients(){
System.out.println("The gates has been opened...");
while (true){
try {
Socket client = servSocket.accept();
processClient(client);
}
catch (IOException ex){
ex.printStackTrace();
}
}
}
private void processClient(Socket client){
writers.add(getClientWriter(client));
startUpdateFrom(client);
System.out.println("New client connected: " + client.getPort());
}
private PrintWriter getClientWriter(Socket client){
try{
return new PrintWriter(client.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
return null;
}
And finally, a new thread starts to listen to any new messages from that client:
private void startUpdateFrom(Socket client){
new Thread(
new WaitAndSendToAllFrom(client))
.start();
}
Which is:
public class WaitAndSendToAllFrom implements Runnable{
BufferedReader reader;
public WaitAndSendToAllFrom(Socket clientSocket){
try{
reader = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
}
catch (IOException ex){
ex.printStackTrace();
}
}
public void run(){
try{
String message;
System.out.println("Thread: waiting for messages to send...");
while (true){
message = reader.readLine();
while (message != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
}
}
catch (IOException ex){
ex.printStackTrace();
}
}
private void sendToAll(String message){
List<PrintWriter> writers = ServerClientConnector.getWriters();
for (PrintWriter pr : writers){
pr.println(message + "\n");
pr.flush();
}
}
}
The cycle gets to the "Thread: waiting for messages to send...", but not any further, reader.readLine() returns null (checked with a sysout :) ). I was trying to debug it, but i'm not so experienced in programing so much, especially debugging two separate codes working with each other. I've been looking at this for 3 days, and i'm seriously stuck here.
while (true){
message = reader.readLine();
while (message != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
}
This makes no sense. You read one line and then keep testing. It for null in a loop in which it can never change.
A proper way to write this is:
while ((message = reader.readLine()) != null){
System.out.println("Server: Sending message: " + message);
sendToAll(message);
}
I'm trying to make a server/client to send text from client to server then sending back an ok message or something similar back to the client, but for some error that I can't see, either the server gets stuck right before sending the ok back to the client, or the client does not receive the message (I think it's the first one though).
Any help is appreciated.
This is the server code:
class ActiveServer extends Thread {
InputStream inStream;
OutputStream outStream;
public ActiveServer(InputStream inStream, OutputStream outStream) {
this.inStream = inStream;
this.outStream = outStream;
}
#Override
public void run() {
boolean ret = false;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
PrintWriter writer = new PrintWriter(outStream);) {
String line = null;
while((line = reader.readLine()) != null) {
String[] str = line.split(";");
line = null;
switch (str[0]) {
case "insert" : //ret = SQLOptions.insert(str[1], str[2]);
System.out.println(str[1]);
break;
}
writer.print(ret);
writer.flush();
// As far as i can see it gets stuck at the end of this while, but I don't know why.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Server {
private static final int PORT = 39165;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT);) {
System.out.println("Servidor online");
ExecutorService service = Executors.newFixedThreadPool(10);
while (true) {
Socket client = server.accept();
InetAddress ip = client.getInetAddress();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date time = new Date();
System.out.print(sdf.format(time));
System.out.println(" " + ip + " connected");
InputStream inStream = client.getInputStream();
OutputStream outStream = client.getOutputStream();
service.execute(new ActiveServer(inStream,outStream));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
And here goes the client code:
public class Telnet {
static Console console = System.console();
public static void connect(String ip, String port) {
try(Socket socket = new Socket(ip, Integer.parseInt(port));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
String msg = null;
while(true) {
msg = console.readLine();
writer.println(msg);
writer.flush();
if (msg.equals(".quit")) {
System.out.println("Exiting...");
break;
}
String input = reader.readLine();
System.out.println(input);
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if(args.length < 2) {
err.println("Telnet <ip> <port>");
return;
}
if (console == null) {
err.println("A console is not available");
return;
}
connect(args[0], args[1]);
}
}
On the server side, you write the response without a terminating newline:
writer.print(ret);
But on the client side, you read until the end of line:
String input = reader.readLine();
The documentation for BufferedReader#readLine says:
Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
Thus, the client will wait forever for the newline sequence which the server will never send.
I wanna write the code to let Client send a string to Server, Server print the string and reply a string, then Client print the string Server reply.
My Server
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = null;
Socket s = null;
try {
ss = new ServerSocket(34000);
s = ss.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
s.getInputStream()));
OutputStreamWriter out = new OutputStreamWriter(s.getOutputStream());
while (true) {
String string = in.readLine();
if (string != null) {
System.out.println("br: " + string);
if (string.equals("end")) {
out.write("to end");
out.flush();
out.close();
System.out.println("end");
// break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
s.close();
ss.close();
}
}
}
My Client:
public class Client {
public static void main(String[] args) {
Socket socket =null;
try {
socket = new Socket("localhost", 34000);
BufferedReader in =new BufferedReader(new InputStreamReader(socket.getInputStream()));
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
String string = "";
string = "end";
out.write(string);
out.flush();
while(true){
String string2 = in.readLine();
if(string2.equals("to end")){
System.out.println("yes sir");
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
System.out.println("closed client");
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
are there some somethings wrong? if i remove the code "while(true) ..." in client class, it's OK.
you should add "\r\n" at the end of the String which write into stream.
example:
client :
string = "end";
out.write(string + "\r\n");
out.flush();
server :
out.write("to end" + "\r\n");
out.flush();
out.close();
System.out.println("end");
// break;
I don't see the server response.
You do a
System.out.println("br: " + string);
but not a
out.write(string);
out.flush();
Appand "\n" to end of the response from server.
outToClient.writeBytes(sb.toString() + "\n");
You are reading lines but you aren't writing lines. Add a newline, or call BufferedReader.newLine().