java.io.EOFException error on object serialization with HttpHandler - java

I am trying to serialize an object in a HttpHandler class.
I have 2 files, Server3.java:
package server3;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class Server3 {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(3333), 0);
server.createContext("/", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
String response = "Kjo eshte nje pergjigje nga serveri! n";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
Personat obj = new Personat();
ObjectOutputStream objOut = new ObjectOutputStream(t.getResponseBody());
objOut.writeObject(obj);
objOut.close();
}
}
}
class Personat implements Serializable{
private static final long serialVersionUID = 1L;
int ID=3;
String Name="Andi";
}
and Client3.java:
package server3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
//te gjithe personat qe jan ne database me nej objekt
public class Client3 {
public static void main(String[] args) throws Exception {
try {
URL url = new URL("http://localhost:3333");
HttpURLConnection s = (HttpURLConnection) url.openConnection();
s.setDoOutput(true);
s.setDoInput(true);
s.setRequestMethod("POST");
s.setUseCaches(false);
InputStream in = s.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
int c;
while ((c = br.read()) != -1) {
System.out.print((char) c);
}
ObjectInputStream ios = new ObjectInputStream(s.getInputStream());
Personat oin = (Personat) ios.readObject();
String emri=oin.Name;
System.out.println(emri);
ios.close();
s.disconnect();
} catch (IOException ex) {
System.err.println(ex);
System.out.print(ex);
}
}
}
But when I run it eclipse shows me
java.io.EOFException Kjo eshte nje pergjigje nga serveri! njava.io.EOFException`
and I cant understand why.

The problem is that you are trying to fit both the string response and the object into response.length() bytes. What happens is that only response.length() bytes are sent and so if you try to read more you get the EOFException.
If you instead set the responseLength parameter to be 0 it will allow you to transmit an arbitrary amount of data
t.sendResponseHeaders(200, 0);
You also shouldn't close the stream if you are going to write more data into it. Don't call os.close() until all the writing is complete.

Related

java get data from api (I want to print the values ​in the url )

I want to print the values ​​in the url but I'm new can you help me?
......................................................
import java.util.*;
import java.io.*;
import java.net.*;
class Main {
public static void main (String[] args) {
System.setProperty("http.agent", "Chrome");
try {
URL url = new URL("https://coderbyte.com/api/challenges/json/rest-get-simple");
try {
URLConnection connection = url.openConnection();
InputStream inputStream = connection.getInputStream();
System.out.println(inputStream);
} catch (IOException ioEx) {
System.out.println(ioEx);
}
} catch (MalformedURLException malEx) {
System.out.println(malEx);
}
}
}
try this
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
public class UrlConnectionReader {
public static void main(String[] args) throws MalformedURLException, IOException {
InputStream in = null;
System.setProperty("http.agent", "Chrome");
try {
in = new URL("https://coderbyte.com/api/challenges/json/rest-get-simple").openStream();
InputStreamReader inR = new InputStreamReader(in);
BufferedReader buf = new BufferedReader(inR);
String line;
while ((line = buf.readLine()) != null) {
System.out.println(line);
}
} finally {
in.close();
}
}
}

Failed to send data stream by sockets in Java

I'm trying to stream audio through TCP sockets in java, using the Java sound api.
Up there all right, the problem comes when the client will play that data buffer that comes from the server, when entering the play method, automatically shows the following error:
Exception in thread "main" javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1121)
at AudioClient.play(AudioClient.java:37)
at AudioClient.main(AudioClient.java:18)
I do not know why he shows it, or what I'm doing wrong.
This is the server code, which looks for the file and sends it to the client
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class AudioServer {
public static void main(String[] args) throws IOException {
File soundFile = AudioUtil.getSoundFile("C:\\Users\\Carlos\\Desktop\\03- Walk.wav");
System.out.println("server: " + soundFile);
try (ServerSocket serverSocker = new ServerSocket(6666);
FileInputStream in = new FileInputStream(soundFile)) {
if (serverSocker.isBound()) {
Socket client = serverSocker.accept();
OutputStream out = client.getOutputStream();
byte buffer[] = new byte[2048];
int count;
while ((count = in.read(buffer)) != -1)
out.write(buffer, 0, count);
}
}
System.out.println("server: shutdown");
}
}
And this is the client code, which captures that data flow and reproduces it
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.Socket;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class AudioClient {
public static void main(String[] args) throws Exception {
// play soundfile from server
System.out.println("Client: reading from 192.168.0.19:6666");
try (Socket socket = new Socket("192.168.0.19", 6666)) {
if (socket.isConnected()) {
InputStream in = new BufferedInputStream(socket.getInputStream());
play(in);
}
}
System.out.println("Client: end");
}
private static synchronized void play(final InputStream in) throws Exception {
AudioInputStream ais = AudioSystem.getAudioInputStream(in);
try (Clip clip = AudioSystem.getClip()) {
clip.open(ais);
clip.start();
Thread.sleep(100); // given clip.drain a chance to start
clip.drain();
}
}
}
Additionally, there is an AudioUtils class, which only contains a static method, this static method only throws an exception in case the file passed by the programmer is not a file or does not exist. The code is the following
import java.io.File;
public class AudioUtil {
public static File getSoundFile(String fileName) {
File soundFile = new File(fileName);
if (!soundFile.exists() || !soundFile.isFile())
throw new IllegalArgumentException("not a file: " + soundFile);
return soundFile;
}
}
It should also be clarified that both classes, both server and controller have the proncipal method because they are 2 separate programs. My question is, how do I solve this error, I really do not know where to start. Thank you

outputstream does not write the data as expected

My server looks like this:
package marshexample;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;
public class marshServer {
private ServerSocket ses;
private Reader br;
private OutputStream os;
public marshServer() {
StringBuilder sb = new StringBuilder();
try {
ses = new ServerSocket(7824);
Socket s = ses.accept();
br = new InputStreamReader(s.getInputStream());
char[] request = new char[6];
int count = br.read(request);
while (!sb.toString().contains("project")) {
sb.append(new String(request, 0, count));
count = br.read(request);
System.out.println(sb.toString());
}
System.out.println(sb);
os = s.getOutputStream();
os.write("string from server".getBytes());
os.write("empty line".getBytes());
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(sb);
}}
The issue is I have to add the string os.write("empty line".getBytes()); in order to make it work correctly. Without this string the massage is not fully sent to the client. (The same situation is with client). So why flush method does not solve this problem? Thank you for any ideas!

java: HTTP session between a HTTP server and a client

I'm using com.sun.net.HttpServer class to build a http server with java like the following:
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class SimpleHttpServer {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8989), 0);
server.createContext("/", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
//Read the request
InputStream in = httpExchange.getRequestBody();
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer);
String inputString = writer.toString();
//prepare the response
httpExchange.sendResponseHeaders(200, "Hi my faithful client".length());
OutputStream os = httpExchange.getResponseBody();
os.write("Hi my faithful client".getBytes());
os.close();
}
}
}
I'm communicating with this server using this client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
public class Main {
public static void main(String argv[]) throws IOException{
String urlstr = "http://127.0.0.1:8989";
URL url = new URL(urlstr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write("Hello HTTP server!! I'm your client1");
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
result.append(line);
System.out.println(result.toString());
}
}
}
and it'fine working.
but what I want now is that the server allows the client to communicate with him for a session that means a sequence of request/response not just only one. So it will be a loop of request/response. For this purpose I tried to add as a first step just one request to the client by adding to it those two lines:
writer.flush();
writer.write("Hello HTTP server!! I'm your client2");
But it doesn't work. Just the first request is caught by the server.
How can I change the code to achieve my purpose?
Please check the code below:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
public class Test1 {
static String urlstr = "http://127.0.0.1:8989";
public static void main(String argv) throws IOException{
URL url = new URL(urlstr);
Test1 t = new Test1();
for (int i = 0; i < 10; i++) {
t.sendRequest("Hello HTTP server!! I'm your client" + i, url);
}
}
private void sendRequest(String strToSend, URL url) throws IOException{
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(strToSend);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
result.append(line);
System.out.println(result.toString());
}
}
}

Avro Communication over TCP Sockets

I am currently working on a project that will involve communication of applications written in C and Java. Therefore, I chose to work with Apache Avro. I have seen on the website that Avro can (de-)serialize objects from files using the DataFileWriter class.
But, in my case I want to use TCP sockets between my applications. Therefore, DataFileWriter class is not going to work for me. After reading the documentation, I have not found any information on how to send objects through TCP sockets.
Any ideas on how to do that? I specifically want to know what kind of Input and Output Streams I should use on the Java Clients.
I have developed the following code for the Java Server:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import middleman.bigpeer.BigPeer;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.io.BinaryDecoder;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;
public class MiddleManWorker implements Runnable {
private InputStream in;
private OutputStream out;
private Socket clientSocket;
public MiddleManWorker(Socket clientSocket, HashMap<Integer, NodeType> dbNodesDirectory,
HashMap<Integer, NodeType> workersDirectory) {
this.clientSocket = clientSocket;
try {
this.in = clientSocket.getInputStream();
this.out = clientSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
EncoderFactory encoderFactory = new EncoderFactory();
DecoderFactory decoderFactory = new DecoderFactory();
BinaryEncoder binaryEncoder = encoderFactory.binaryEncoder(out, null);
BinaryDecoder binaryDecoder = decoderFactory.binaryDecoder(in, null);
SpecificDatumReader<BigPeer> peerDatumReader = new SpecificDatumReader<BigPeer>(BigPeer.class);
BigPeer bigPeer = null;
SpecificDatumWriter<BigPeer> writer = new SpecificDatumWriter<BigPeer>();
try {
peerDatumReader.read(bigPeer, binaryDecoder);
System.out.println("Received: " + bigPeer.getType());
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.write(bigPeer, binaryEncoder);
} catch (IOException e) {
e.printStackTrace();
}
}
}
A sample Java Client is the following:
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import middleman.bigpeer.BigPeer;
import org.apache.avro.io.BinaryDecoder;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;
public class SystemClient {
public static void connect(String serverIPAddress, Integer serverPort) throws IOException, ClassNotFoundException {
/**
* Create Connection with the server
*/
Socket socket = new Socket(serverIPAddress, serverPort);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
EncoderFactory encoderFactory = new EncoderFactory();
DecoderFactory decoderFactory = new DecoderFactory();
BinaryEncoder binaryEncoder = encoderFactory.binaryEncoder(out, null);
BinaryDecoder binaryDecoder = decoderFactory.binaryDecoder(in, null);
BigPeer bigPeer = new BigPeer();
bigPeer.setType("test");
SpecificDatumReader<BigPeer> reader = new SpecificDatumReader<BigPeer>(BigPeer.class);
SpecificDatumWriter<BigPeer> writer = new SpecificDatumWriter<BigPeer>(BigPeer.class);
System.out.println("Before: " + bigPeer.getType());
writer.write(bigPeer, binaryEncoder);
System.out.println("Waiting for response...");
reader.read(bigPeer, binaryDecoder);
System.out.println("After: " + bigPeer.getType());
}
}
And the server seems to halt on the peerDatumReader.read(bigPeer, binaryDecoder); line of code. Any ideas?
Thank you,
Nick
BinaryEncoder uses an internal buffer for performance reasons. You may need to call flush on the encoder to send the data through the pipe.
See the reference for more information on this behaviour:
The BinaryEncoder implementation returned may buffer its output. Data may not appear on the underlying OutputStream until Flushable.flush() is called. The buffer size is configured with configureBufferSize(int).
If buffering is not desired, and lower performance is acceptable, use directBinaryEncoder(OutputStream, BinaryEncoder)

Categories

Resources