I am trying to create a program that will get data directly from socket instead of going through using HttpURLConnection or HttpClient. Using a socket will give me more freedom to manipulate the data to match the requirements. I am hoping that using sockets, I can preserve the chunk headers sent with each chunk. Following is my code to accomplish that. Unfortunately, even though the code runs without any errors, it runs for at least 40 seconds before it stops. Also, I don't get any InputStream from the server even though I checked that the program was connected to the server.
Socket socket = new Socket(hostAddr, port);
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
char[] streamBuff = new char[8192];
StringBuilder receivedData = new StringBuilder();
int count = 0;
while((count = isr.read(streamBuff)) > 0)
{
receivedData.append(streamBuff, 0, count);
}
System.out.println(receivedData);
HTTP/1.1 has persistent connections. You are reading all response chunks in that loop and then block until server times out and closes you TCP connection.
Edit 0:
By the way, you are not sending a *request* to the server, that's why you don't get anything back. Study the protocol if you want to implement it yourself.
You first need to make a request, either GET or POST. Here's an example to show how to do use openStream() and then read the InputStream:
public class DateWala {
public static void main(String[] args){
try {
URL url = new URL("http://www.google.com");
InputStream is = url.openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String s = null;
while ((s=br.readLine())!=null){
System.out.println(s);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I am attempting to read an input stream from a socket provided by a web browser client. Every approach I have taken has got the same results thus far, it just hangs and I don't know why. I have tried mark() marking the read limit to what is available and still no go.
inputStream.mark(inputStream.available());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int read;
while((read = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, read);
}
byte[] bytes = outputStream.toByteArray();
I have also tried clientSocket.shutdownInput() to tried to fix this issue, still no good.
Here is my attempt below:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Server {
public static void main(String[] args)
{
ServerSocket server = null;
try {
// Server is listening on port 3001
server = new ServerSocket(3001, 1, InetAddress.getByName("localhost"));
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to Server
System.out.println("New client connected"
+ client.getInetAddress()
.getHostAddress());
// create a new thread object
ClientHandler clientSock
= new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
}catch (IOException e) {
e.printStackTrace();
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
public void run() {
InputStream inputStream = null;
OutputStream clientOutput = null;
try {
inputStream = clientSocket.getInputStream();
inputStream.mark(inputStream.available());
clientSocket.shutdownInput();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int numRead;
while((numRead = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, numRead);
}
byte[] bytes = outputStream.toByteArray();
String payloadString = new String(bytes, StandardCharsets.UTF_8);
System.out.println(payloadString);
clientOutput = clientSocket.getOutputStream();
clientOutput.write(("HTTP/1.1 \r\n" + "200 OK").getBytes());
clientOutput.write(("ContentType: " + "text/html" + "\r\n").getBytes());
clientOutput.write("\r\n".getBytes());
clientOutput.write("Hello World!".getBytes());
clientOutput.write("\r\n\r\n".getBytes());
clientOutput.flush();
inputStream.close();
clientOutput.close();
try{
clientSocket.close();
}catch(Exception ex){
ex.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any help would be most appreciated! Thank you.
browsers suggests you should toss this all in the garbage and use HTTP, because, well, browsers.
But, if you insist, there are two problems here.
You've made it crazy complicated.
You can take all of that code and replace it all with this simple little line:
byte[] bytes = in.readAllBytes();
That replaces the lines starting with in.mark(in.available()) (this line does nothing at all, I have no idea where you got this from. If you think it is supposed to do something specific, you might want to mention that. Because it doesn't do anything. mark is useful if you ever reset, which you aren't, and you don't need to here, hence, useless), all the way to `byte[] bytes =...;
sockets don't close unless sender goes out of its way to close it
Your read code (yours, or the much simpler one-liner above) reads everything until the stream closes. In your second snippet, you close it right away, which obviously doesn't work. You cannot know when to close it, the sender does this job. Evidently it's not doing it.
I advise you to adapt protocols that pre-roll sizes, so you know how much to read and aren't dependent on closing the socket just to signal that the data is sent.
For example:
byte[] sizeRaw = in.readNBytes(4);
int size = ByteBuffer.wrap(bytes).getInt();
byte[] bytes = in.readNBytes(size);
You will of course have to adjust the sending code to send the size first (as a 32-bit value, big endian). One way or another you have to look at the sending code here. Either fix it so that it closes once done, or, better yet, adjust it so it sends size first.
At the moment I'm trying to develop an Android Application for Instant Messaging. I want to use ejabberd for this on an Ubuntu Server. There is just one problem.
When I try to connect to my ejabberd first with this xml-line:
<stream:stream to='x.x.x.x' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
it takes very long to receive the answer (about 20 seconds, sometimes longer).
I just have this problem, when I send some "good" data to the Server. Sending some "bad" data, i receive the Error message very fast.
It's performed by an Android IntentService
I will Post my Code here too:
the attributes:
private Socket socket;
private String host = "x.x.x.x";
private int port = 5222;
private OutputStream out = null;
private String in = null;
the doInBackground():
this.socket = new Socket(host,port);
if(!this.socket.isConnected()){
Log.e("Socket","Socket nicht geöffnet");
}else{
Log.e("Socket","Socket erfolgreich geöffnet");
//create output stream
try {
this.out = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
//write to output stream
StringBuffer stringbuffer = new StringBuffer();
stringbuffer.append("<stream:stream to='5.175.8.41' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>");
//convert into bits and give it to outputstream
try {
this.out.write(String.valueOf(stringbuffer).getBytes("UTF-8"),0,String.valueOf(stringbuffer).getBytes().length);
out.flush();
Log.e("Connecting-out","Erstes Tupel erfolgreich gesendet.");
} catch (IOException e) {
e.printStackTrace();
}
//receive the answer from server
try {
Log.e("lol","lol");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"),200);
StringBuilder builder = new StringBuilder();
String aux;
aux = in.readLine();
this.in = builder.toString();
Log.e("...",aux);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("Connecting-in",in);
i think especially these lines
StringBuilder builder = new StringBuilder();
String aux;
aux = in.readLine();
this.in = builder.toString();
take very long. But the strange thing is , that the Error message is read very fast. So it has to be the Server?
Can someone please help me?
Thanks in advance :)
You used readLine() and it waits for new line character.
On error, server generally disconnects the connection.
It is why you get error answer immediately.
I suggest you not using readLine().
How can i send a strin using getOutputStream method. It can only send byte as they mentioned. So far I can send a byte. but not a string value.
public void sendToPort() throws IOException {
Socket socket = null;
try {
socket = new Socket("ip address", 4014);
socket.getOutputStream().write(2); // have to insert the string
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
socket.close();
}
}
Thanks in advance
How about using PrintWriter:
OutputStream outstream = socket .getOutputStream();
PrintWriter out = new PrintWriter(outstream);
String toSend = "String to send";
out.print(toSend );
EDIT: Found my own answer and saw an improvement was discussed but left out. Here is a better way to write strings using OutputStreamWriter:
// Use encoding of your choice
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(fileDir), "UTF8"));
// append and flush in logical chunks
out.append(toSend).append("\n");
out.append("appending more before flushing").append("\n");
out.flush();
Use OutputStreamWriter class to achieve what you want
public void sendToPort() throws IOException {
Socket socket = null;
OutputStreamWriter osw;
String str = "Hello World";
try {
socket = new Socket("ip address", 4014);
osw =new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
osw.write(str, 0, str.length());
} catch (IOException e) {
System.err.print(e);
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
socket.close();
}
}
Two options:
Wrap your OutputStream in an OutputStreamWriter, so you can then send the string
Convert a string to bytes using String.getBytes(encoding)
Note that in both cases you should specify the encoding explicitly, e.g. "UTF-8" - that avoids it just using the platform default encoding (which is almost always a bad idea).
This will just send the character data itself though - if you need to send several strings, and the other end needs to know where each one starts and ends, you'll need a more complicated protocol. If it's Java on both ends, you could use DataInputStream and DataOutputStream; otherwise you may want to come up with your own protocol (assuming it isn't fixed already).
if you have a simple string you can do
socket.getOutputStream().write("your string".getBytes("US-ASCII")); // or UTF-8 or any other applicable encoding...
You can use OutputStreamWriter like this:
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
out.write("SomeString", 0, "SomeString".length);
You may want to specify charset, such as "UTF-8" "UTF-16"......
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream(),
"UTF-8");
out.write("SomeString", 0, "SomeString".length);
Or PrintStream:
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("SomeString");
Or DataOutputStream:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes("SomeString");
out.writeChars("SomeString");
out.writeUTF("SomeString");
Or you can find more Writers and OutputStreams in
The java.io package
public void sendToPort() throws IOException {
DataOutputStream dataOutputStream = null;
Socket socket = null;
try {
socket = new Socket("ip address", 4014);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF("2"); // have to insert the string
} catch (UnknownHostException e) {
System.err.print(e);
} finally {
if(socket != null) {
socket.close();
}
if(dataOutputStream != null) {
dataOutputStream.close();
}
}
}
NOTE: You will need to use DataInputStream readUTF() method from the receiving side.
NOTE: you have to check for null in the "finally" caluse; otherwise you will run into NullPointerException later on.
I see a bunch of very valid solutions in this post. My favorite is using Apache Commons to do the write operation:
IOUtils.write(CharSequence, OutputStream, Charset)
basically doing for instance:
IOUtils.write("Your String", socket.getOutputStream(), "UTF-8")
and catching the appropriate exceptions. If you're trying to build some sort of protocol you can look into the Apache commons-net library for some hints.
You can never go wrong with that. And there are many other useful methods and classes in Apache commons-io that will save you time.
Old posts, but I can see same defect in most of the posts. Before closing the socket, flush the stream. Like in #Josnidhin's answer:
public void sendToPort() throws IOException {
Socket socket = null;
OutputStreamWriter osw;
String str = "Hello World";
try {
socket = new Socket("ip address", 4014);
osw =new OutputStreamWriter(socket.getOutputStream(), 'UTF-8');
osw.write(str, 0, str.length());
osw.flush();
} catch (IOException e) {
System.err.print(e);
} finally {
socket.close();
}
}
I'm building a Java client application which needs to send a message to a server and receive a response afterwards. I can send the message successfully, the problem is that I can't get the response because I get an IO exception ("Socked is closed") when trying to read the 'BufferedReader'.
This is my code, so far:
public class MyClass {
/**
* #param args the command line arguments
*/
#SuppressWarnings("empty-statement")
public static void main(String[] args) {
JSONObject j = new JSONObject();
try {
j.put("comando", 1);
j.put("versao", 1);
j.put("senha", "c4ca4238a0b923820dcc509a6f75849b");
j.put("usuario", "1");
j.put("deviceId", "1");
} catch (JSONException ex) {
System.out.println("JSON Exception reached");
}
String LoginString = "{comando':1,'versao':1,'senha':'c4ca4238a0b923820dcc509a6f75849b','usuario':'1','deviceId':'1'}";
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("10.1.1.12", 3333);
System.out.println("Connected to the server successfully");
PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(),true);
outToServer.println(j.toString());
outToServer.close();
System.out.println("TO SERVER: " + j.toString());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String resposta = inFromServer.readLine();
System.out.println("FROM SERVER: " + resposta);
clientSocket.close();
} catch (UnknownHostException ex) {
System.out.println("Could not connect to the server [Unknown exception]");
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
I know that the socket is being closed because of the OutToServer.close() but closing the stream is the only way to send the message. How should I approach this situation?
flush() is not the case when it comes with new PrintWriter(, true).
The real problem is that you are closing the PrintWriter outToServer which wraps the underlying InputStream, again, came from the Socket.
When you close the outToServer you're closing the whole socket.
You have to use Socket#shutdownOutput().
You don't even have to close the output if you want to keep the socket's in/out channels for further communications.
flush() when you are done with any writeXXX. Those writeXXX practically don't mean you sent those bytes and characters to other side of the socket.
You may have to close the output, and output only, to signal the server that you sent all you had to send. This is really a matter of the server-side socket's desire.
final Socket socket = new Socket(...);
try {
final PrintStream out = new PrintStream(socket.getOutputStream());
// write here
out.flush(); // this is important.
socket.shutdownOutput(); // half closing
// socket is still alive
// read input here
} finally {
socket.close();
}
Try to call outToServer.flush()
That will try to flush the data from the buffer, although it still not guarantees that it will be sent.
I am trying to send a file (an image sent as a byte array) with the client and then the server should receive said byte array to make further use of it. However when I click on the "send" to send the image the file transfer starts (as I get a sentImage.jpg in my Desktop) but it gets stuck for some reason I can't figure out and the image never gets correctly sent.
Here's the part that receives from the server (it already accepted the connection):
public void run(){
try {
byte[] receivedData = new byte[1024];
BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
// while(bis.read() != -1){
s.acquireUninterruptibly();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Admin\\Desktop\\sentImage.jpg"));
while ((incoming = bis.read(receivedData)) != -1) {
bos.write(receivedData, 0, incoming);
}
s.release();
n.release();
bis.close();
bos.flush();
// }
} catch (IOException e) {
e.printStackTrace();
}
}
and the client is sending here:
public void sendImageResult() {
new Thread(new Runnable() {
public void run() {
try {
int inside = 0;
Socket socket = new Socket("localhost", 4444);
File myImageFile = new File("C:\\Users\\Admin\\Desktop\\test.jpg");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myImageFile));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream( ));
byte[] byteArray = new byte[1024];
while ((inside = bis.read(byteArray)) != -1){
bos.write(byteArray,0,inside);
}
bis.close();
bos.flush();
} catch (UnknownHostException ex) {
System.out.println("No se pudo establecer la conexión.");
ex.printStackTrace();
} catch (FileNotFoundException fnf){
fnf.printStackTrace();
} catch(IOException ioe){
ioe.printStackTrace();
}
}
}).start();
}
It does not appear that the OutputStream (bos) that is used to write to disk is being closed. This could lead to unexpected results.
As jt said, the OutputStream writing to disk is not being closed, but neither is the OutputStream being used to send the data, nor is the Socket being closed from the sending side. The sending side may be buffering the data at the tcp level, waiting for more bytes before sending the last packet. You are calling flush, but that can be ignored, it's not guaranteed to work like you expect. Another thing to try is calling shutdownOutput on the Socket and seeing if that forces it to flush. You can also try setTcpNoDelay(true) when you open the Socket. If none of that works, get a tcp trace program (I like tcpdump) and use it to see if the packets are actually being sent, it will at least narrow it down to either the send or receive end of things.