I'm trying write my individual HTTP Server and I need a help .
What is the method of ServerSocket or Socket class can to invoke on the URL and brining it into a code.
For example, if I write following link <b>http://localhost:8080/coupon/add?name=coupon name</b> in browser, I would be want to get this link into my code.
Maybe who know how can I do this?
my simple code:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class HTTPServer {
public static void main(String[] args) {
new HTTPServer().startServer();
}
public void startServer() {
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("Server is started");
while (true) {
Socket socket = serverSocket.accept();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks
All your code does right now is set up a TCP server.
HTTP is a Layer 7 protocol.
Once you accept the connection from the client, HTTP can be used for communication over that TCP socket.
You'd have to parse the HTTP request that the client sends, and from that, you'd know the URL.
In your case, you said:
I write following link http://localhost:8080/coupon/add?name=coupon name in browser
Your browser will send an HTTP request like the following example:
GET /coupon/add?name=coupon+name HTTP/1.0
Host: localhost:8080
In reality, there will be more HTTP headers there, as well as a trailing \r\n, but for our sake, let's keep it simple.
Note that special characters like space are URL-encoded, however space is also encoded as + in the query string - it could be either + or %20 depending on the client.
Hopefully it's reasonably clear to you from this explanation how you get the URL from this HTTP request.
The only missing part from the actual full link is the http:// part. The distinction between HTTP and HTTPS is not part of the HTTP protocol - it's above the socket layer but below the HTTP protocol layer. If you had SSL sockets, you'd know that on the server side, and determine based on whether it was an SSL socket or a "plain" socket, whether it was http or https.
Hope that helps.
I improved for testing the startServer method for getting information.
I'm trying to include the data that comes from URL from any browsers to URI or URL class of JAVA.
This impossible ? Maybe who know how can I do this ?
public void startServer() {
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("Server is started");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("SERVER SOCKET TESTS:");
System.out.println("getChannel: " + serverSocket.getChannel());
System.out.println("getInetAddress: " + serverSocket.getInetAddress());
System.out.println("getLocalPort: " + serverSocket.getLocalPort());
System.out.println("getLocalSocketAddress: " + serverSocket.getLocalSocketAddress());
System.out.println();
System.out.println("CLIENT SOCKET TESTS:");
System.out.println("getChannel: " + socket.getChannel());
System.out.println("getLocalAddress: " + socket.getLocalAddress());
System.out.println("getLocalPort: " + socket.getLocalPort());
System.out.println("getLocalSocketAddress: " + socket.getLocalSocketAddress());
System.out.println("getRemoteSocketAddress: " + socket.getRemoteSocketAddress());
System.out.println("getInetAddress: " + socket.getInetAddress());
System.out.println("getInputStream: " + socket.getInputStream());
System.out.println("getOutputStream: " + socket.getOutputStream());
System.out.println();
System.out.println("URI - GET INFORMATION:");
URI uri = new URI("httpscheme://world.hello.com/thismy?parameter=value");
System.out.println(uri.getHost());
System.out.println(uri.getPath());
System.out.println(uri.getQuery());
System.out.println(uri.getScheme());
}
} catch (Exception e) {
System.out.println("error");
}
}
little test:
when I run code and after that open the browser and I write in my browser, for example: http://localhost:8080 I get information, but I don't understand following:
why the serverSocket object in getInetAddress method (serverSocket.getInetAddress) have an IP4 and it 0.0.0.0 (why not a standard local ip that defined on my computer) and the socket object of getInetAddress method (socket.getInetAddress) have an IP6 and it 0:0:0:0:0:0:0:1 . How can I get a standard host name localhost how to get the URI class (with chunks of data of link)?
The port is gated nice: 8080.
The problem for getting URL path , solved.
package pk6HttpServer;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Created by Morris on 08/10/16.
*/
public class HTTPServer {
private static String headerData;
public static void main(String[] args) {
new HTTPServer().startServer();
}
public void startServer() {
try (ServerSocket serverSocket = new ServerSocket(8080)) {
boolean isClosed = false;
System.out.println("Server is started");
while (true) {
Socket socket = serverSocket.accept();
try {
try (InputStream raw = socket.getInputStream()) { // ARM
System.out.println("=================BEFORE STARTING READING HEADER =======================");
System.out.println("Collecting data to string array...");
headerData = getHeaderToArray(raw);
//
System.out.println("+++++++++++++++++ AFTER ENDING READING HEADER +++++++++++++++++++++++");
System.out.println("Hello World");
}
} catch (MalformedURLException ex) {
System.err.println(socket.getLocalAddress() + " is not a parseable URL");
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
} catch (Exception ex) {
System.out.println("error# " + ex.getMessage());
}
}
public static String getHeaderToArray(InputStream inputStream) {
String headerTempData = "";
// chain the InputStream to a Reader
Reader reader = new InputStreamReader(inputStream);
try {
int c;
while ((c = reader.read()) != -1) {
System.out.print((char) c);
headerTempData += (char) c;
if (headerTempData.contains("\r\n\r\n"))
break;
}
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
headerData = headerTempData;
return headerTempData;
}
}
Related
I am new to working with sockets, and I am working on this project where a connection between my android flutter app and a java server is needed, to do this I am trying socket programming.
The server code is fairly simple, I create a new thread for every client connected and I give them a bunch of URLs, later on, this should be replaced by a query result. here is the java code:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CrawlitServer {
// The port number on which the server will listen for incoming connections.
public static final int PORT = 6666;
//main method
public static void main(String[] args) {
System.out.println("The server started .. ");
// Create a new server socket
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(PORT);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
// Listen for incoming connections and create a new thread for each one
while (true) {
try {
new CrawlitServerThread(serverSocket.accept()).start();
}
catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
public static class CrawlitServerThread extends Thread {
private final Socket socket;
public CrawlitServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
List<String> list = new ArrayList<>();
//assign a value to list
list.add("http://www.google.com");
list.add("http://www.yahoo.com");
list.add("http://www.bing.com");
list.add("http://www.facebook.com");
list.add("http://www.twitter.com");
list.add("http://www.linkedin.com");
list.add("http://www.youtube.com");
list.add("http://www.wikipedia.com");
list.add("http://www.amazon.com");
list.add("http://www.ebay.com");
list.add("http://stackoverflow.com");
list.add("http://github.com");
list.add("http://quora.com");
list.add("http://reddit.com");
list.add("http://wikipedia.org");
try {
// Get the input stream from the socket
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
Scanner scanner = new Scanner(inputStream);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
PrintWriter writer = new PrintWriter(outputStream, true);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println("Received Message from client: " + line);
writer.println(list + "\n");
}
}
catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
}
Now I run this server and connect to it using sockets in Flutter, I give it the IP address I get from the ipconfig command, and here is the dart code:
import 'dart:async';
import 'dart:io';
//Utilities that manage connections with server sockets.
//ServerUtil Class
class ServerUtil {
static const port = 6666;
static const host = MY_IP_GOES_HERE;
static late Socket socket;
static bool connected = false;
//a list of urls returned by the server
static List<String> urls = [];
//Constructor
ServerUtil() {
//Initialize the socket.
Socket.connect(host, port).then((Socket sock) {
socket = sock;
connected = true;
socket.listen(dataHandler,
onError: errorHandler, onDone: doneHandler, cancelOnError: false);
//send a message to the server.
}).catchError((e) {
print("Unable to connect: $e");
});
}
//Query method that sends a message to the server. The server will return a list of urls.
//The urls will be added to the urls list.
//The urls list will be returned.
static Future<List<String>> query(String userQuery) async {
urls.clear();
//check if socket is connected.
if (connected) {
//send the query to the server.
socket.writeln(userQuery);
await Future.delayed(const Duration(milliseconds: 200));
print(urls);
return urls;
}
//if socket is not connected, wait for 5 seconds and try again.
await Future.delayed(const Duration(milliseconds: 50));
return query(userQuery);
}
//Handles data from the server.
void dataHandler(data) {
//String of received data.
String dataString = String.fromCharCodes(data).trim();
//remove first and last character from the string.
dataString = dataString.substring(1, dataString.length - 1);
//remove all the whitespace characters from the string.
dataString = dataString.replaceAll(RegExp(r'\s+'), '');
urls = dataString.split(',');
}
//Handles errors from the server.
void errorHandler(error, StackTrace trace) {
print(error);
}
//Handles when the connection is done.
void doneHandler() {
socket.destroy();
}
}
This works perfectly fine while using a debug apk running it on my real Note 9 device. The problem however is that when I build a release apk and try it out, nothing happens.
The way I set it up is that I wait for the query method in an async and then I send the result to a new screen and push that screen into the navigator.
But in the release apk nothing happens, the new screen doesn't load.
So this leads me to my first question:
Is there a way to debug a release apk? see what exceptions it throws or print some stuff to console?
I have the server running on my Laptop, and the app runs on my phone which is on the same WIFI network.
My second question is:
Do I need to enable some sort of option with my router or my laptop to allow my phone to connect? it does connect in debug mode without any modifications
I tried some random things, like using 'localhost' instead of my IP, as I would normally connect say with a java client for example, but it didn't work.
My last question is:
Does the release apk or like android OS prevent connections to local hosts, maybe because it thinks it is not secure? but then it still connects in debug mode.
Thank you for your time.
I'm creating one java http server, that usues html5 to play music.
The problem is that when I connect to the server over my browser ( chromium, firefox) it does not play the audio. But if I select to my browser show me the font code and I copy the font code and paste it on a file .html and I open this file with browser its works. What is my problem?
This is my java server
package br.ufla.sd.trabfinal;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerHttp extends Thread {
private Socket clientSocket;
private static ServerSocket serverSocket;
private static int portNumber = 8088;
private PrintWriter out;
/**
* WebServer constructor.
*/
private ServerHttp(Socket clientSoc) {
clientSocket = clientSoc;
start();
}
public static void main(String args[]) {
serverSocket = null;
try {
serverSocket = new ServerSocket(portNumber);
System.out.println("Connection Socket Created");
try {
while (true) {
System.out.println("Waiting for Connection");
new ServerHttp(serverSocket.accept());
}
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
} catch (IOException e) {
System.err.println("Could not listen on port:" + portNumber);
System.exit(1);
} finally {
try {
serverSocket.close();
} catch (IOException e) {
System.err.println("Could not close port: " + portNumber);
System.exit(1);
}
}
}
public void run() {
System.out.println("New Communication, Thread " + this.getId()
+ " Started");
try {
// remote is now the connected socket
System.out.println("Connection, sending data.");
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream());
// read the data sent. We basically ignore it,
// stop reading once a blank line is hit. This
// blank line signals the end of the client HTTP
// headers.
String str = ".";
while (!str.equals(""))
str = in.readLine();
// Send the response
// Send the headers
out.println("HTTP/1.1 200 OK");
//out.println("Content-Type: text/html");
//out.println("Server: Bot");
// this blank line signals the end of the headers
out.println("");
// Send the HTML page
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset=\"UTF-8\">");
out.println("<title> Músicas</title>");
out.println("</head>");
out.println("<body>");
out.println("<H1>Welcome</H1>");
out.println("<audio controls>");
out.println("<source src=\"/****/Horse.wav\" type=\"audio/wav\">");
out.println("Your browser does not support the audio element.");
out.println("</audio>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
And another thing, if I change the file location to a online sound like this site : Site sound it works... Is someone know what is my problem?
Thanks!!
The problem is that you are just giving a path to the audio source. Think what will happen once this page loads on a browser and the user clicks to start the audio file.
Your browser will send a request again to the server to fetch the audio file. At this point in time, your server should accept the request and send the audio file back to the browser as an output stream.
The external link works because the file is present at the external link.
For your browser, the file is not present as your server doesn't seem to return any file for the request that the browser is making.
To confirm this you can check your browser's console. You will get a 404 for the audio file.
Hello I am trying to send an object to a server, and then after the server has received it, taking that same object from the server and reading it as a String in the client output. My initial sent message seems to work while everything after that isnt, here is my code:
import java.io.*;
import java.net.*;
public class GUGLi {
static Socket socket = null;
static ObjectOutputStream out = null;
static ObjectInputStream in = null;
String host = "host";
public static void main(String[] args) throws IOException {
try {
OpenPort();
InfoSent();
ReadInfo();
String line;
while ((line = in.toString()) != null) {
System.out.println(line);
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + "host");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: " + "host");
System.exit(1);
in.close();
socket.close();
out.close();
}
}
public static void OpenPort() throws UnknownHostException, IOException{
socket = new Socket ("host", 7879);
}
public static void InfoSent()throws IOException {
Student info = new Student (22, "Guglielmo", "Male",
"email", "#");
out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(info);
System.out.println("Sent: " + info);
out.flush();
}
public static void ReadInfo()throws IOException {
in = new ObjectInputStream(socket.getInputStream());
}
}
line = in.toString() doesn't read lines. It turns an InputStream into its string representation. You need to invoke a read method. If you are hoping to read lines you need BufferedInputStream.readLine(). But if you're reading objects over the same socket you can't mix stream/reader types, so you should read with readUTF() and write with writeUTF() at the other end.
The first problem you have is you're not calling a reading method as sais by #EJP, so see his answer to have more details.
EDIT: I've deleted the information about not being able to receive data in your InputStream. I was wrong about thinking that your socket was not connected to another client, cause i was thinking that String host = "host" would connect to the loopback address, and I was not seeing any code to send data back to your InputStream.
I suggest that you read some tutorials to clear that out. I suggest you Java tutorial about socket to have a strong basic. It will explain everything you need.
I am creating a multithread server program to display the browser's request when it try to connect to localhost.
I found only IE9 on my Windows works as expected but not Firefox 19, Chrome, Opera. The are simply sitting there to wait for my program response.
What I have missed?
import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HTTPEchoServer {
private static final String serverName = "HTTPEchoServer";
private static final int port = 80;
private static final String CRLF = "\r\n";
private static final Logger logger = Logger.getLogger(serverName);
private static void printHeader(PrintWriter out) {
out.println("HTTP/1.0 200 OK\r\n" + "Server: " + serverName + CRLF
+ "Content-Type: text/html" + CRLF + CRLF
+ "<!DOCTYPE HTML PUBLIC "
+ "\"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+ "<HTML>\n"
+ "<HEAD>\n"
+ " <TITLE>" + "HTTP Echo Server Result</TITLE>\n"
+ "</HEAD>\n"
+ "<H1>HTML Received from HTTP Echo Server</H1>\n"
+ "<B>Here is the request sent by your browser:</B>\n"
+ "<PRE>");
}
private static void printTrailer(PrintWriter out) {
out.println("</PRE>\n" + "</BODY>\n" + "</HTML>\n");
}
static class ClientHandler extends Thread {
Socket socket = null;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
logger.log(Level.INFO, "Accepted client {0}:{1}",
new Object[]{socket.getInetAddress(), socket.getPort()});
try {
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
try (PrintWriter writer = new PrintWriter(os, true)) {
synchronized (this) {
printHeader(writer);
writer.flush();
BufferedReader reader = new BufferedReader
(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
writer.println(line);
writer.flush();
}
printTrailer(writer);
writer.flush();
writer.close();
}
}
socket.close();
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
logger.log(Level.INFO, "Disconnected client {0}:{1}",
new Object[]{socket.getInetAddress(), socket.getPort()});
}
}
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(port);
logger.log(Level.INFO, "Server started, listening at port {0} ...", port);
ExecutorService executor = Executors.newCachedThreadPool();
while (true) {
Socket socket = server.accept();
ClientHandler handler = new ClientHandler(socket);
executor.execute(handler);
}
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
}
Also, I found I cannot run this program on the OS X unless I change the port to 8080. I have already disabled the firewall on my OS X 10.8.2 computer. The error I get is:
<pre>
java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at HTTPEcho.HTTPEchoServer.main(HTTPEchoServer.java:80)
</pre>
You cannot open server socket in applet in all browsers except MSIE. This is done because opening server socket is security violation. If you do want to do this you have to sign your applet.
I hope that I understood your correctly that your code is running in applet environment (because you mentioned browsers) although I cannot see this facet from your stack trace that starts from main().
EDIT:
I read your post again and understood that your question actually contains 2 questions: first about applets and second about running as application under Unix. For unix #Anders R. Bystrup gave you the answer: only root can listen to ports under 1024. So, you have to run your program as root or using sudo.
BTW it seems that you are on the wrong way. Could you probably explain what would you like to achieve and community probably can give you a tip for better solution.
As the exception itself says java.net.BindException: Permission denied. You need to be root user to bind ports below 1024. If you are on linux you san do sudo java HTTPEchoServer to start the server.
Other possibility may be that you already have a server running on port 80.
Port 80 is reserved HTTP port, there are other ports aswell which are reserved.
ports 1 through 1023 for administrative functions leaving port numbers greater than 1024 available for use.
How to find available port
I'm trying to create a simple Flash chat application for educational purposes, but I'm stuck trying to send a policy file from my Java server to the Flash app (after several hours of googling with little luck).
The policy file request reaches the server that sends a harcoded policy xml back to the app, but the Flash app doesn't seem to react to it at all until it gives me a security sandbox error.
I'm loading the policy file using the following code in the client:
Security.loadPolicyFile("xmlsocket://myhostname:" + PORT);
The server recognizes the request as "<policy-file-request/>" and responds by sending the following xml string to the client:
public static final String POLICY_XML =
"<?xml version=\"1.0\"?>"
+ "<cross-domain-policy>"
+ "<allow-access-from domain=\"*\" to-ports=\"*\" />"
+ "</cross-domain-policy>";
The code used to send it looks like this:
try {
_dataOut.write(PolicyServer.POLICY_XML + (char)0x00);
_dataOut.flush();
System.out.println("Policy sent to client: " + PolicyServer.POLICY_XML);
} catch (Exception e) {
trace(e);
}
Did I mess something up with the xml or is there something else I might have overlooked?
I've seen your approach and after some time trying i wrote a working class, listening on any port you want:
package Server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class PolicyServer {
public static final String POLICY_XML =
"<?xml version=\"1.0\"?>"
+ "<cross-domain-policy>"
+ "<allow-access-from domain=\"*\" to-ports=\"*\" />"
+ "</cross-domain-policy>";
public PolicyServer(){
ServerSocket ss = null;
try {
ss = new ServerSocket(843);
} catch (IOException e) {e.printStackTrace();}
while(true){
try {
final Socket client = ss.accept();
new Thread(new Runnable() {
#Override
public void run() {
try {
client.setSoTimeout(10000); //clean failed connections
client.getOutputStream().write(PolicyServer.POLICY_XML.getBytes());
client.getOutputStream().write(0x00); //write required endbit
client.getOutputStream().flush();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
//reading two lines emties flashs buffer and magically it works!
in.readLine();
in.readLine();
} catch (IOException e) {
}
}
}).start();
} catch (Exception e) {}
}
}
}
Try add \n at the end of policy xml.