Android - Socket like http server, sending embed image to browser - java

I implemented for my android application a simple HTTP Server which pass html tags with sockets and everything went as expected.
But I'm tried load in the client(browser) an simple embed image (http://localhost:1234/img.jpg\" />) and I don't know how to make the socket load it.
Can anyone help me giving the coordinates to make it?
My simple http server:
public class MainClass extends Activity {
// Called when the activity is first created
// It was called from onCreate method surrounded with try catch
[...]
ServerSocket ss = new ServerSocket(1234);
while (true) {
Socket s = ss.accept();
PrintStream out = new PrintStream(s.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String info = null;
while ((info = in.readLine()) != null) {
System.out.println("now got " + info);
if(info.equals(""))
break;
}
out.println("HTTP/1.0 200 OK");
out.println("MIME_version:1.0");
out.println("Content_Type:text/html");
String c = "<html>" +
"<head></head>" +
"<body>" +
"<img src=\"http://localhost:1234/img.jpg\" />" + // << Does not load in the browser
"<h1> hi </h1>" +
"</body>" +
"</html>";
out.println("Content_Length:" + c.length());
out.println("");
out.println(c);
out.close();
s.close();
in.close();
}
[...]
}
}
Thanks in advance!

The reason why the image is not loading is because the file http://localhost:1234/img.jpg is not being served by your application. When an <img /> tag is processed, the browser will go out to the src path and load that file into the page.
I don't know how to implement that offhand (I have not implemented HTTP before). But you would at least have to process the inputed GET request, and differentiate between the base webpage and the image request.

Related

retrieve file from remote ftp to a webserver

Sorry if this seems like a dumb question, but I just start the ftp and webserver thing so I get a little bit confused about it, particularly about the InputStream, fileInputStream and outputStream etc this kind of concepts. So I try to extend the program I write called web server and make it act as a FTP client that request txt file only. So when request a text file (.txt) from within my web browser, the web server will not have a copy of this file. It will instantiate an FtpClient, retrieve the text file from your local FTP server and then send it back to your web browser as an HTTP response.
My code works fine for web server part, following is part of my code:
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input stream filters.
BufferedReader br = new BufferedReader(new InputStreamReader(is));
...
// Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
// skip over the method, which should be "GET"
tokens.nextToken();
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "HTTP/1.1 200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
}
// file doesn't exist
else {
// if the file requested is any type other than a text (.txt) file,
// report // error to the web client
if (!contentType(fileName).equalsIgnoreCase("text/plain")) {
statusLine = "404 Not Found" + CRLF;
contentTypeLine = "no content" + CRLF;
entityBody = "<HTML>" + "<HEAD><TITLE>Not Found</TITLE></HEAD>" + "<BODY>Not Found</BODY></HTML>";
} else {
String server = "127.0.0.1";
// else retrieve the text (.txt) file from your local FTP server
statusLine = "200 OK" + CRLF;
contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
// create an instance of ftp client
FTPClient ftp = new FTPClient();
// connect to the ftp server
ftp.connect(server);
ftp.login(userName, password);
// retrieve the file from the ftp server, remember you need to
// // first upload this file to the ftp server under your user
// ftp directory
ftp.retrieveFile("/folder1/"+ fileName.substring(1), os);
// disconnect from ftp server
ftp.disconnect();
// assign input stream to read the recently ftp-downloaded file
fis = new FileInputStream(fileName);
}
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeLine);
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes(entityBody);
}
os.close();
br.close();
socket.close();
where things get confusing is that in the ftp retrieve part, I don't know if I use the correct method and if I should using "os" the DataOutputStream as argument or something else. Not fully understand the input and output stream thing. what I'm sure is that I want to use
fis = new FileInputStream(fileName);
after I retrieve the file from ftp server.
So can anyone tell me what should I use in the retrieve part?
Thanks!

Why did my application stop connecting using HTTP, and how can I debug it?

I have a program that includes HTTP connection to a PLM application that runs on SQL Server. The program is scheduled to run daily. It collects data from few sources, then issues a query to the PLM to store the data, and finally reads the PLM's reply to verify if the data was properly stored.
The application ran OK, until we upgraded both the DB (into SQL Server 2012) and the PLM.
Since then the upgrade, when the program establishes the connection it receives OK status; however, the data setting query does not affect the data base, and there is no answer received. There are no error messages - just malfunction.
My major question is - how to debug it. I know whet I send and what I receive. How can I get more data on what happens in between?
I attach the code for review. What I didn't add here is the query itself, which is WML-like string. The PLM should fire an answer regardless the query it receives, even if it is an error message. However, I get only NULL.
public Boolean amlArasCommunication (String data , int targetDbType, String passWord)
{
final String url = "http://plm-srv/InnovatorServer/Server/InnovatorServer2012.aspx";
final String schemeUrl = "'http://schemas.xmlsoap.org/soap/envelope/'";
String answer =””;
String dataBase = data base name;
Writer wout;
HttpURLConnection amlConnection = null;
try
{
// instantiate the HttpURLConnection with the URL object - A new connection is
// opened every time by calling the openConnection method of the protocol
// handler for this URL. This is the point where the connection is opened.
amlConnection = (HttpURLConnection) new URL(url).openConnection();
amlConnection.setDoOutput(true);
amlConnection.setDoInput(true);
amlConnection.setRequestMethod("POST");
amlConnection.setRequestProperty("SOAPAction", "ApplyAML");
amlConnection.setConnectTimeout(10000);
amlConnection.setReadTimeout(10000);
amlConnection.setRequestProperty("AUTHUSER", "Admin");
amlConnection.setRequestProperty("AUTHPASSWORD", calcMD5(passWord));
amlConnection.setRequestProperty("DATABASE", dataBase);
String query = "<?xml version='1.0'?>\r\n" +
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=" + schemeUrl + ">\r\n" +
" <SOAP-ENV:Body>\r\n" +
data +
" </SOAP-ENV:Body>\r\n" +
"</SOAP-ENV:Envelope>\r\n";
// instantiate OutputStreamWriter using the output stream, returned from getOutputStream, that writes
// to this connection. If an I/O error occurs while creating the output stream, IOException will be fired.
wout = new OutputStreamWriter(amlConnection.getOutputStream());
wout.write (query);
wout.close();
// At this point, we've sent all the data. The outputStream was closed, while the connection is still open
int result;
if ((result = amlConnection.getResponseCode()) == HttpURLConnection.HTTP_OK)
{
// Get the communication results from the PLM
InputStream ac = amlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader (ac);
BufferedReader in = new BufferedReader(isr);
String readResult = in.readLine ();
int count = 0;
while (readResult != null)
{
answer += readResult + "\n";
readResult = in.readLine ();
count++;
}
in.close();
if (answer.contains("fault"))
System.out.println ("Error message: " + answer + "\nQuery: " + query);
else
log.message ("Lines count=" + count + "; com status=" + result + "; reply: " + answer, false);
}
else
// Error code is returned, or no status code is returned, do stuff in the else block
System.out.println("Connection failed with the following code: " + result);
}
catch (IOException e) { ; }
if (amlConnection != null)
amlConnection.disconnect ();
return true;
}
I think you will have to look into the log files of the PLM application to find out why you do not get an HTTP response. There might be a number of possible reasons why the application is not working anymore after the upgrade.
I guess that it will be difficult to debug the problem based on the client code only. As the server seems to accept your HTTP, I would expect that this event and errors would be written to a log file somewhere. You might also want to try some graphical tool like SOAP UI to test the SOAP service.

How I can develop an "xdcc send" in Java?

I found this code to communicate with an IRC server (see below). However I did not find how to send a command to download or upload in xdcc.
Once connected to the IRC server and positioned in the channel. I want to send a command like.
/msg bot_name xdcc send #number_of_file
Thank you in advance for your answers, examples and help.
import java.io.*;
import java.net.*;
public class HackBot {
public static void main(String[] args) throws Exception {
// The server to connect to and our details.
String server = "irc.freenode.net";
String nick = "simple_bot";
String login = "simple_bot";
// The channel which the bot will join.
String channel = "#irchacks";
// Connect directly to the IRC server.
Socket socket = new Socket(server, 6667);
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream( )));
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream( )));
// Log on to the server.
writer.write("NICK " + nick + "\r\n");
writer.write("USER " + login + " 8 * : Java IRC Hacks Bot\r\n");
writer.flush( );
// Read lines from the server until it tells us we have connected.
String line = null;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
System.out.println("Nickname is already in use.");
return;
}
}
// Join the channel.
writer.write("JOIN " + channel + "\r\n");
writer.flush( );
// Keep reading lines from the server.
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase( ).startsWith("PING ")) {
// We must respond to PINGs to avoid being disconnected.
writer.write("PONG " + line.substring(5) + "\r\n");
writer.write("PRIVMSG " + channel + " :I got pinged!\r\n");
writer.flush( );
}
else {
// Print the raw line received by the bot.
System.out.println(line);
}
}
}
}
Your code shows only the minimum requirements needed to open a connection to a IRC server and keep it connected, actually the entire IRC protocol is much more complex and it is not implemented in the code.
The xdcc send is simply a normal IRC message sent privately to a specific other user (usually a bot) of the IRC server, therefore you can send it by using the command PRIVMSG:
writer.write("PRIVMSG " + botNickName + " :xdcc send #" + numberOfPack + "\r\n");
where botNickName and numberOfPack are two String variables containing the nickname of the bot (i.e. the recepient of the message) and the number (in string format) of the package in which you are interested.
Nevertheless you must consider that the DCC is an entire completely different protocol from the IRC protocol itself: it uses the CTCP message on IRC:
DCC SEND <filename> <ip> <port>
only to start a DCC session, but then there is the DCC protocol in order to manage the communication client-to-client. So if you really want to make the DCC works you should also implement it, but it would not be a quick job.

Sending HTTP request's

I am writing a web client. I have the following code.
public class Connection extends Thread{
public final static int PORT = 1337;
private ServerSocket svrSocket = null;
private Socket con = null;
public Connection(){
try{
svrSocket = new ServerSocket(PORT);
System.out.println("Conected to: " + PORT);
}catch(IOException ex)
{
System.err.println(ex);
System.out.println("Unable to attach to port");
}
}
public void run(){
while(true)
{
try{
con = svrSocket.accept();//on this part the program stops
System.out.println("Client request accepted");
PrintWriter out = new PrintWriter(con.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
out.println("GET /<index.html> HTTP/1.1");
out.println("***CLOSE***");
System.out.println(in.readLine());
/*
String s;
while((s = in.readLine()) != null)
{
System.out.println(s);
}*/
out.flush();
out.close();
in.close();
con.close();
System.out.println("all closed");
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
}
The run method will be used latter on. That I have is a file called index.html. This file is in the same file as the java code. What I am trying to do with the request is send the HTML file. But if I run this program on a web browser localhost:1337 the following gets displayed.
GET /<index.html> HTTP/1.1
***CLOSE***
This should not get displayed. The page that results of the HTML code in the index.html should get displayed.
Index.html code:
<html>
<head>
<title> </title>
</head>
<body bgcolor = "#ffffcc" text = "#000000">
<h1>Hello</h1>
<p>This is a simple web page</p>
</body>
</html>
How do I get this html page to display in the browser?
Thank you
t seems that all is good on your code, it seems you need to read the HTTP header from the input stream so you can get the requested file name and then use the Socket output stream to write the response from the file.
OutputStream output = con.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String fileName = readHeader(in);
String baseDir = System.getProperty("my.base.dir", "/home/myname/httpserver");
boolean exist = true;
InputStream fileIn = null;
try {
File requestedFile = new File(baseDir, fileName);
fileIn = new FileInputStream(requestedFile);
} catch(Exception e){
exist = false;
}
String server = "Java Http Server";
String statusLine = null;
String typeLine = null;
String body = null;
String lengthLine = "error";
if (exist) {
statusLine = "HTTP/1.0 200 OK" + "\r\n";
//get content type by extension
typeLine = "Content-type: html/text \r\n";
lengthLine = "Content-Length: " + (new Integer(fileIn.available())).toString() + "\r\n";
} else {
statusLine = "HTTP/1.0 404 Not Found" + CRLF;
typeLine = "text/html";
body = "<HTML>" + "<HEAD><TITLE>404</TITLE></HEAD>" + "<BODY>404 Not Found"+"</BODY></HTML>";
}
output.write(statusLine.getBytes());
output.write(server.getBytes());
output.write(typeLine.getBytes());
output.write(lengthLine.getBytes());
output.write("\r\n".getBytes());
if (exist) {
byte[] buffer = new byte[1024];
int bytes = 0;
while ((bytes = fileIn.read(buffer)) != -1) {
output.write(buffer, 0, bytes);
}
} else {
output.write(body.getBytes());
}
//close sreams
You are confusing a couple of things. First of all: what you are writing is a server, not a client.
Second: You are not following the HTT Protocol.
The line GET /<index.html> HTTP/1.1 (which is wrong, it should be GET /index.html HTTP/1.1) is a request that is sent by the client (like a web browser). Instead, it is your server sending this.
A quick solution:
Instead of sending this static text (the line with the GET and the one with the ***CLOSE***), read the content of your index.html file and print it to your out stream.
EDIT: Here's a quick overview of the http data flow:
The client (e.g. a browser) connects to the server
The client sends it's request, something like
GET /theFileIWant.html HTTP/1.1\r\n
Host: localhost\r\n
\r\n
at this point, the client usually stops sending anything and waits for the server to respond. That is called the "request/response" model.
The server reads the request data and finds out what it has to do.
The output (in this case: a file's content) is sent to the client, preceded by HTTP response headers.
The connection can be kept open or closed, depending on the HTTP headers of both client's request and server's response.

Java constructing an http request message

I asked a similar question in another thread but I think I'm just having trouble getting the syntax right at this point. I basically want to open a socket in Java, send a HTTP request message to get the header fields of a specific web page. My program looks like this so far:
String server = "www.w3.org";
int port = 80;
String uri = "/Protocols/rfc2616/rfc2616-sec5.html#sec5.1"
Socket socket = new Socket(server, port);
PrintStream output = new PrintStream(socket.getOutputStream());
BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println("HEAD " + uri + " HTTP/1.1");
//String response = "";
String line = "";
while((line = socketInput.readLine()) != null){
System.out.println(line);
}
socketInput.close();
socket.close();
It doesn't really work. Or it doesn't work for all websites. If someone could just tell me the immediate problems with what I'm doing, that would be great. Thank you!
Change
output.println("HEAD " + uri + " HTTP/1.1");
to
output.println("HEAD " + uri + " HTTP/1.1");
output.println("Host: " + server);
output.println();
You have to send the Host header because usually there are more than one virtual host on one IP address. If you use HTTP/1.0 it works without the Host header.
I would use some higher-level component, like HttpURLConnection (see here) or apache http components.

Categories