i have to do a practice in my uni, it must create a blockchain using sockets and serialization in a "simple way". But when exiting the loop (typing "NO") It creates a EOF exception that i cannot solve, while closing the socket(s.close()). i would appreciate some help, i am not vry good at java. here are my classes.
Client
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client implements Runnable{
public static void main(String[] args) throws Exception {
(new Thread(new Client())).start();
}
public static MedicalReport createReport(){
return new MedicalReport(10,"pepe","id","record");
}
#Override
public void run() {
// int port = 12345;
// String computer = "localhost";
try{
Socket s = new Socket("localhost", 12348);
ObjectOutputStream p = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
/* PrintWriter print = new PrintWriter(s.getOutputStream());
print.println("ready");
print.flush();*/
//manda informe al servidor serializado y espera respuesta
boolean stop = false;
while(!stop){
try{
MedicalReport report = createReport();
p.writeObject(report);
p.flush();
p.reset();
System.out.println("Do you want to continue? Yes or No");
Scanner in1 = new Scanner (System.in);
String answer="";
if(in1.hasNextLine())
answer = in1.nextLine();
if(!answer.equalsIgnoreCase("yes")){
System.out.println(report);
stop = true;
}
}
catch(Exception e){
System.out.println(e);
}
}
try{
s.close();
}
catch(Exception e){
System.out.println(e);
}
}catch(Exception e){
System.out.println(e);
}
}
}
SERVER
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
public class Server {
public static void main(String[] args)
throws Exception
{
ArrayList<Block> blockChain = new ArrayList<>();
try{
ServerSocket ss = new ServerSocket(12348);
Socket s = ss.accept();
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
/* Scanner scanner = new Scanner(s.getInputStream());
String text = scanner.nextLine();*/
int i = 0;
int previousHash = 0;
while (i != 20){
MedicalReport rp = (MedicalReport)in.readObject();
Block block = new Block(rp,previousHash);
blockChain.add(block);
System.out.println("Block " + blockChain.size() + " added to blockchain");
System.out.println(blockChain.get(i));
previousHash = block.getBlockHash();
System.out.println(blockChain);
i++;
}
try{
ss.close();
}
catch(Exception e){
System.out.println(e);
}
}catch(Exception e){
System.out.println(e);
}
}
}
It looks like the error is while closing the socket, any idea?
EDIT REST OF THE CODE
MEDICAL REPORT
import java.io.Serializable;
public class MedicalReport implements Serializable {
private int age;
private String name;
private String id;
private String record;
private static final long serialVersionUID = 1L;
public MedicalReport(){super();}
public MedicalReport(int age, String name, String id, String record) {
super();
this.age = age;
this.name = name;
this.id = id;
this.record = record;
}
public String getRecord(){
return this.record;
}
public String toString(){
return this.name + ". \n" + this.age + ". \n" + this.id + ". \n" + this.record;
}
}
BLOCK
public class Block {
private int blockHash;
private int previousHash;
private MedicalReport report;
//Block Constructor.
public Block(MedicalReport report,int previousHash ) {
this.previousHash = previousHash;
this.report = report;
this.blockHash = report.hashCode();
}
public int getPreviousHash() {
return previousHash;
}
public MedicalReport getReport() {
return report;
}
public int getBlockHash() {
return blockHash;
}
}
EDIT 2
FIRST QUESTION SOLVED. Now i get this error when exiting the loop:
java.net.SocketException: Connection reset by peer: socket write error
readObject() throws EOFEzception when the peer has closed the connection. This is normal. Catch it and stop reading. There is no problem here to solve.
IMPORTANT: As EJP said EOFException is normal and you can control the flow of your code with it but if you still want to know how to do in the way you asked here it is. REMEMBER THIS IS JUST FULFILL YOUR QUESTION AND NOT ADVISED TO DO SO.
On Server Class
Replace
MedicalReport rp = (MedicalReport)in.readObject();
With
MedicalReport rp;
if((rp = (MedicalReport)in.readObject())==null) break;
On Client Class
ADD
p.writeObject(null);
Just above the s.close(); statement
You must know that when a peer close the connection normally then
read() returns -1,
readLine() returns null,
readXXX() throws EOFException for any other XXX
And A write will throw an IOException
Related
So I have a client written in Java that i want to use to test out sending email but instead of using an already existing SMTP like google, i want to have my own local server to test out sending mock emails between two mock emails.
I've been trying to look all over the internet for good sources on how to code a simple SMTP Server but i've had zero luck.
I do have a basic server code that when i run it, i can connect my Client to it but at the moment it won't handle any email functionality.
TCPServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.*;
import java.net.*;
public class TCPServer{
private ServerSocket server;
/**
* The TCPServer constructor initiate the socket
* #param ipAddress
* #param port
* #throws Exception
*/
public TCPServer(String ipAddress, int port) throws Exception {
if (ipAddress != null && !ipAddress.isEmpty())
this.server = new ServerSocket(port, 1, InetAddress.getByName(ipAddress));
else
this.server = new ServerSocket(0, 1, InetAddress.getLocalHost());
}
/**
* The listen method listen to incoming client's datagrams and requests
* #throws Exception
*/
private void listen() throws Exception {
// listen to incoming client's requests via the ServerSocket
//add your code here
String data = null;
Socket client = this.server.accept();
String clientAddress = client.getInetAddress().getHostAddress();
System.out.println("\r\nNew client connection from " + clientAddress);
// print received datagrams from client
//add your code here
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
while ( (data = in.readLine()) != null ) {
System.out.println("\r\nMessage from " + clientAddress + ": " + data);
client.sendUrgentData(1);
}
}
public InetAddress getSocketAddress() {
return this.server.getInetAddress();
}
public int getPort() {
return this.server.getLocalPort();
}
public static void main(String[] args) throws Exception {
// set the server address (IP) and port number
//add your code here
String serverIP = "192.168.1.235"; // local IP address
int port = 8088;
if (args.length > 0) {
serverIP = args[0];
port = Integer.parseInt(args[1]);
}
// call the constructor and pass the IP and port
//add your code here
TCPServer server = new TCPServer(serverIP, port);
System.out.println("\r\nRunning Server: " +
"Host=" + server.getSocketAddress().getHostAddress() +
" Port=" + server.getPort());
server.listen();
}
}
What can i add to my existing server code to make it handle email for my Client. I'll also post my email client as well.
ClientTester.java
import java.io.*;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* This program demonstrates a TCP client
* #author jl922223
* #version 1.0
* #since 2020-12-12
*/
public class ClientTester{
private Socket tcpSocket;
private InetAddress serverAddress;
private int serverPort;
private Scanner scanner;
/**
* #param serverAddress
* #param serverPort
* #throws Exception
*/
private ClientTester(InetAddress serverAddress, int serverPort) throws Exception {
this.serverAddress = serverAddress;
this.serverPort = serverPort;
//Initiate the connection with the server using Socket.
//For this, creates a stream socket and connects it to the specified port number at the specified IP address.
//add your code here
this.tcpSocket = new Socket(this.serverAddress, this.serverPort);
this.scanner = new Scanner(System.in);
}
/**
* The start method connect to the server and datagrams
* #throws IOException
*/
/* private void start() throws IOException {
String input;
//create a new PrintWriter from an existing OutputStream (i.e., tcpSocket).
//This convenience constructor creates the necessary intermediateOutputStreamWriter, which will convert characters into bytes using the default character encoding
//You may add your code in a loop so that client can keep send datagrams to server
//add your code here
while (true) {
System.out.print ("C:");
input = scanner.nextLine();
PrintWriter output = new PrintWriter(this.tcpSocket.getOutputStream(), true);
output.println(input);
output.flush();
}
}*/
public static void main(String[] args) throws Exception {
// set the server address (IP) and port number
//add your code here
//IP: 192.168.1.235
//Port: 8088
InetAddress serverIP = InetAddress.getByName("smtp.google.com"); // local IP address
int port = 25;
if (args.length > 0) {
serverIP = InetAddress.getByName(args[0]);
port = Integer.parseInt(args[1]);
}
// call the constructor and pass the IP and port
//add your code here
ClientTester client = new ClientTester(serverIP, port);
// client.start();
try{
client = new ClientTester(serverIP, port);
System.out.println("\r\n Connected to Server: " + client.tcpSocket.getInetAddress());
BufferedReader stdin;
stdin = new BufferedReader (new InputStreamReader (System.in));
InputStream is = client.tcpSocket.getInputStream ();
BufferedReader sockin;
sockin = new BufferedReader (new InputStreamReader (is));
OutputStream os = client.tcpSocket.getOutputStream();
PrintWriter sockout;
sockout = new PrintWriter (os, true);
System.out.println ("S:" + sockin.readLine ());
while (true){
System.out.print ("C:");
String cmd = stdin.readLine ();
sockout.println (cmd);
String reply = sockin.readLine ();
System.out.println ("S:" + reply);
if (cmd.toLowerCase ().startsWith ("data") &&
reply.substring (0, 3).equals ("354"))
{
do
{
cmd = stdin.readLine ();
if (cmd != null && cmd.length () > 1 &&
cmd.charAt (0) == '.')
cmd = "."; // Must be no chars after . char.
sockout.println (cmd);
if (cmd.equals ("."))
break;
}
while (true);
// Read a reply string from the SMTP server program.
reply = sockin.readLine ();
// Display the first line of this reply string.
System.out.println ("S:" + reply);
continue;
}
// If the QUIT command was entered, quit.
if (cmd.toLowerCase ().startsWith ("quit"))
break;
}
}
catch (IOException e)
{
System.out.println (e.toString ());
}
finally
{
try
{
// Attempt to close the client socket.
if (client != null)
client.tcpSocket.close();
}
catch (IOException e)
{
}
}
}
}
The good news is that the ClientTester works when i connect it to smtp.google.com but i don't want to use Googles, i want to have my own basic Email server in java.
Okay, found this early-development standalone version.
Use this INSTEAD of your code; does everything your code does an more.
Single-threaded ServerSocket handling, so only one connection at a time.
package jc.lib.io.net.email.smtp.test1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import jc.lib.io.net.email.JcEMailBasics;
public class Test_SMTP_Server {
static public boolean DEBUG = true;
public static void main(final String s[]) throws UnknownHostException, IOException {
final Test_SMTP_Server server = new Test_SMTP_Server(JcEMailBasics.SMTP_PORTS);
server.start();
try {
Thread.sleep(1 * 60 * 60 * 1000);
} catch (final InterruptedException e) { /* */ }
}
/*
* OBJECT
*/
private final ServerSocket[] mSockets;
private volatile boolean mStopRequested;
private static boolean mReceivingData;
public Test_SMTP_Server(final int[] pPorts) throws IOException {
mSockets = new ServerSocket[pPorts.length];
for (int i = 0; i < pPorts.length; i++) {
final int port = pPorts[i];
try {
mSockets[i] = new ServerSocket(port);
} catch (final java.net.BindException e) {
new java.net.BindException("When mountin port " + port + ": " + e.getMessage()).printStackTrace();
}
System.out.println("Created server socket on port " + port);
}
}
public void start() {
mStopRequested = false;
for (final ServerSocket ss : mSockets) {
if (ss == null) continue;
final Thread t = new Thread(() -> handleServerSocket(ss), "handleServerSocket(" + ss.getLocalPort() + ")");
t.setDaemon(true);
t.start();
}
}
private void handleServerSocket(final ServerSocket pSS) {
final String name = "handleServerSocket(" + pSS.getLocalPort() + ")";
while (!mStopRequested) {
System.out.println(name + "\tListening for connection...");
try (final Socket socket = pSS.accept();
final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), JcEMailBasics.DEFAULT_CHARSET_SMTP_POP3));
final BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), JcEMailBasics.DEFAULT_CHARSET_SMTP_POP3));) {
System.out.println(name + "\tGot new Socket.");
handle(socket, in, out);
System.out.println(name + "\tClosing Socket.");
} catch (final IOException e) {
System.err.println("In " + name + ":");
e.printStackTrace();
}
System.out.println(name + "\tComm Done.");
}
}
public void stop() {
mStopRequested = true;
for (final ServerSocket ss : mSockets) {
try {
ss.close();
} catch (final Exception e) { /* */ }
}
}
static private void handle(final Socket pSocket, final BufferedReader pBR, final BufferedWriter pBW) throws IOException {
// send("+OK POP3 server ready <" + Test_EMails.SERVICE_ADDRESS + ">", out);
send("220 cbsoft.dev SMTP " + JcEMailBasics.NAME, pBW);
final StringBuilder sb = new StringBuilder();
mainLoop: while (!pSocket.isClosed()) {
final String read = read(pBR);
if (read == null) break;
switch (read) {
case JcEMailBasics.COMMAND_DATA: {
send("354 End data with <CR><LF>.<CR><LF>", pBW);
mReceivingData = true;
break;
}
case JcEMailBasics.COMMAND_END_OF_DATA: {
send("250 OK", pBW);
mReceivingData = false;
break;
}
case JcEMailBasics.COMMAND_QUIT: {
send("221 " + JcEMailBasics.NAME + " signing off", pBW);
break mainLoop;
}
default: {
final String correctedRead = read.startsWith(".") ? read.substring(1) : read;
sb.append(correctedRead + "\n");
if (!mReceivingData) send("250 Ok", pBW);
}
}
}
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
final File file = new File("mails/inc_" + sdf.format(new Date()) + ".email.txt");
file.getParentFile().mkdirs();
final String msg = sb.toString();
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(msg.getBytes());
}
System.out.println("File saved as " + file.getCanonicalPath());
}
static private void send(final String pMessage, final BufferedWriter pBW) {
try {
pBW.write(pMessage + "\n");
pBW.flush();
if (DEBUG) System.out.println("SENT:\t" + pMessage);
} catch (final Exception e) {
e.printStackTrace();
}
}
static private String read(final BufferedReader pBR) throws IOException {
try {
final String reply = pBR.readLine();
if (DEBUG) System.out.println("RECV:\t" + reply);
return reply;
} catch (final SocketTimeoutException e) {
System.err.println("SERVER TIMEOUT");
}
return null;
}
}
the only additional file you will need (also included in my previous answer; edited a bit):
package jc.lib.io.net.email;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
public class JcEMailBasics {
static public final int SMTP_PORT_1 = 25;
static public final int SMTP_PORT_2 = 587;
static public final int SMTP_PORT_3 = 465;
static public final int[] SMTP_PORTS = { SMTP_PORT_1, SMTP_PORT_2, SMTP_PORT_3 };
static public final int POP_PORT_1 = 110;
static public final int POP_PORT_SSL = 995;
static public final int POP_PORT_KERBEROS = 1109;
static public final int[] POP_PORTS = { POP_PORT_1, POP_PORT_SSL, POP_PORT_KERBEROS };
// netstat -aon | findstr '587'
static public final String DEFAULT_CHARSET_SMTP_POP3 = "8859_1";
static public final String NAME = "JC Oblivionat0r POP3 Server";
static public final String SERVICE_ADDRESS = "oblivionat0r#cbsoft.dev";
static public final String CONNECTION_CLOSED = "CONNECTION_CLOSED_dtnt495n3479r5zb3tr47c3b49c3";
static public final String COMMAND_QUIT = "QUIT";
static public final String COMMAND_DATA = "DATA";
static public final String COMMAND_END_OF_DATA = ".";
static public void send(final BufferedWriter pBufferedWriter, final String pMessage) throws IOException {
pBufferedWriter.write(pMessage + "\n");
pBufferedWriter.flush();
System.out.println("SENT:\t" + pMessage);
}
static public String sendExpect(final BufferedWriter pBufferedWriter, final String pMessage, final BufferedReader pBufferedReader, final String... pExpectedResponsePrefixes) throws IOException {
send(pBufferedWriter, pMessage);
final String read = read(pBufferedReader);
for (final String erp : pExpectedResponsePrefixes) {
if (read.startsWith(erp)) return read;
}
throw new IllegalStateException("Bad response: Expected [" + toString(", ", pExpectedResponsePrefixes) + "] got [" + read + "] instead!");
}
static public String read(final BufferedReader pBufferedReader) throws IOException {
final String reply = pBufferedReader.readLine();
System.out.println("RECV:\t" + reply);
return reply;
}
#SafeVarargs public static <T> String toString(final String pSeparator, final T... pObjects) {
if (pObjects == null) return null;
final StringBuilder ret = new StringBuilder();
for (final T o : pObjects) {
ret.append(o + pSeparator);
}
if (ret.length() > 0) ret.setLength(ret.length() - pSeparator.length());
return ret.toString();
}
}
Basically like my code.
It is just a proof of concept, and quite unsafe and inefficient
I'm using lombok. The read() method is basically a BufferedReader.readLine() call on the socket's InputStream.
send() is a writeLine
My entry point handleSocket() is when the Socket connection is established.
The String.toNLine() method is a Lombok extension, you can replace it with string.replace("\r\n" , "\n");
Be aware that this is simply a stupid implementation that can be fooled easily, but it enables basic email receiving. You get ALL the communication in the StringBuilder. You could take that final whole text apart with MIME classes (Header / newline / newline body method that is used by HTTP, SMTP etc).
This approach collects the whole comunication first, then later (outside given code) handles the actual MIME part. You could also implement it differently, as in the code knows the current state of transmission and details of the MIME object it's currently receiving, and updates its status/workflow with each line. That would be much more efficient, but the code would be a bit more complex.
package jc.lib.io.net.email.smtp.server.receiver;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import jc.lib.aop.lombok.java.lang.JcAString;
import jc.lib.collection.tuples.JcTriple;
import jc.lib.io.net.email.JcEMailBasics;
import jc.lib.io.net.email.util.JcAServerSocketHandlerBase;
import jc.lib.lang.thread.event.JcEvent;
import lombok.experimental.ExtensionMethod;
#ExtensionMethod({ JcAString.class })
public class JcSmtpReceiverSocketHandler extends JcAServerSocketHandlerBase {
public final JcEvent<JcTriple<JcSmtpReceiver, JcSmtpReceiverSocketHandler, File>> EVENT_EMAIL_RECEIVED = new JcEvent<>();
private final JcSmtpReceiver mJcAServerBase;
private boolean mReceivingData;
public JcSmtpReceiverSocketHandler(final JcSmtpReceiver pJcAServerBase, final ServerSocket pServerSocket, final Socket pSocket) throws IOException {
super(pServerSocket, pSocket);
mJcAServerBase = pJcAServerBase;
}
#Override protected void handleSocket() throws IOException {
send("220 cbsoft.dev SMTP " + JcEMailBasics.NAME);
final StringBuilder sb = new StringBuilder();
mainLoop: while (!mSocket.isClosed()) {
final String read = read();
if (read == null) break;
switch (read) {
case JcEMailBasics.COMMAND_DATA: {
send("354 End data with <CR><LF>.<CR><LF>");
mReceivingData = true;
break;
}
case JcEMailBasics.COMMAND_END_OF_DATA: {
send("250 OK");
mReceivingData = false;
break;
}
case JcEMailBasics.COMMAND_QUIT: {
send("221 " + JcEMailBasics.NAME + " signing off");
break mainLoop;
}
default: {
final String correctedRead = read.startsWith(".") ? read.substring(1) : read;
sb.append(correctedRead + "\n");
if (!mReceivingData) send("250 Ok");
}
}
}
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
final File file = new File("mails/inc_" + sdf.format(new Date()) + ".email.txt");
file.getParentFile().mkdirs();
String msg = sb.toString();
msg = msg.toNLineBreak();
final String header = msg.subStringBefore("\n\n");
System.out.println("header:");
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(msg.getBytes());
}
System.out.println("File saved as " + file.getCanonicalPath());
EVENT_EMAIL_RECEIVED.trigger(new JcTriple<>(mJcAServerBase, this, file));
}
}
Check out this file for some ports and other info.
package jc.lib.io.net.email;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import jc.lib.io.net.email.util.JcAServerBase;
import jc.lib.lang.JcUArray;
public class JcEMailBasics {
static public final int SMTP_PORT_1 = 25;
static public final int SMTP_PORT_2 = 587;
static public final int SMTP_PORT_3 = 465;
static public final int[] SMTP_PORTS = { SMTP_PORT_1, SMTP_PORT_2, SMTP_PORT_3 };
static public final int POP_PORT_1 = 110;
static public final int POP_PORT_SSL = 995;
static public final int POP_PORT_KERBEROS = 1109;
static public final int[] POP_PORTS = { POP_PORT_1, POP_PORT_SSL, POP_PORT_KERBEROS };
// netstat -aon | findstr '587'
static public final String DEFAULT_CHARSET_SMTP_POP3 = "8859_1";
static public final String NAME = "JC Oblivionat0r POP3 Server";
static public final String SERVICE_ADDRESS = "oblivionat0r#cbsoft.dev";
static public final String CONNECTION_CLOSED = "CONNECTION_CLOSED_dtnt495n3479r5zb3tr47c3b49c3";
static public final String COMMAND_QUIT = "QUIT";
static public final String COMMAND_DATA = "DATA";
static public final String COMMAND_END_OF_DATA = ".";
static public void send(final BufferedWriter pBufferedWriter, final String pMessage) throws IOException {
pBufferedWriter.write(pMessage + "\n");
pBufferedWriter.flush();
if (JcAServerBase.DEBUG) System.out.println("SENT:\t" + pMessage);
}
static public String sendExpect(final BufferedWriter pBufferedWriter, final String pMessage, final BufferedReader pBufferedReader, final String... pExpectedResponsePrefixes) throws IOException {
send(pBufferedWriter, pMessage);
final String read = read(pBufferedReader);
for (final String erp : pExpectedResponsePrefixes) {
if (read.startsWith(erp)) return read;
}
throw new IllegalStateException("Bad response: Expected [" + JcUArray.toString(", ", pExpectedResponsePrefixes) + "] got [" + read + "] instead!");
}
static public String read(final BufferedReader pBufferedReader) throws IOException {
final String reply = pBufferedReader.readLine();
if (JcAServerBase.DEBUG) System.out.println("RECV:\t" + reply);
return reply;
}
}
You need to communicate with the client.
First let the server send something like "220 Smtp server" (only 220 matters) to the client.
I used PrintWriter:
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
out.println("220 Smtp server");
Then you will receive an EHLO from the client while getting lines from the inputStream.
Here you can find an example of the communication between server an client (without the starting message from the server (220)):
https://postmarkapp.com/guides/everything-you-need-to-know-about-smtp#basic-smtp-commands
I am developing a web server(experimenting with network programming in java) using Java SE only, everything seems to be working well (i.e HTML and CSS files) but the problem is with images, they are written to browser as bytes with the correct mime type and the correct size but the problem is that they wont display on the web browser, its showing a black Screen, developers tool on Google Chrome shows the image has been properly downloaded with a status code of 200 OK and the correct file size . Below is my code.
package miniserver;
import java.io.*;
import java.io.FileInputStream;
import java.util.Scanner;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;
enum status_code{
OK(200),NOT_FOUND(404),FORBIDDEN(403);
private int code;
status_code(int code){
this.code=code;
}
public int getCode(){
return this.code;
}
}
public class MiniServer {
public static void main(String[] args) {
try{
InetAddress address = InetAddress.getLocalHost();
try{
ServerSocket webserver = new ServerSocket(1521);
System.out.println("Web Sever Started");
System.out.println("Running On " + address.getHostAddress());
Date k= new Date();
System.out.println(k.toString());
Socket browser ;
while(true){
browser=webserver.accept();
requestHandler handle = new requestHandler(browser);
}
}catch(IOException err){
System.out.println("Server Already Running"+err.getMessage());
}
}catch(UnknownHostException ex){
Logger.getLogger(MiniServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class requestHandler implements Runnable{
static int nRequest=0;
private Socket client;
private BufferedOutputStream stream;
FileOutputStream out;
BufferedOutputStream response;
BufferedReader request;
requestHandler(Socket client){
try{
this.client=client;
this.response=new BufferedOutputStream (client.getOutputStream());
this.request=new BufferedReader( new InputStreamReader(client.getInputStream()));
new Thread(this).start();
}catch(IOException e){
}
}
#Override
public void run(){
try{
Scanner header = new Scanner(this.request);
String rf="";
String firstline=null;
try{
firstline=header.nextLine();
rf =firstline.split("\\s")[1].split("\\?")[0];
System.out.println(rf);
}catch(NoSuchElementException err){
System.out.println("NO HEADERS FOUND"+err.getMessage());
}
fileInputStream page;
fileInputStream errorpage=new fileInputStream("web/index.html");
status_code code=null;
String type="";
if(firstline.startsWith(".5.")){
page=errorpage;
code=status_code.FORBIDDEN;
}else if(rf.equals("/")){
this.out = new FileOutputStream("test/index.html");
type="text/html";
page = new fileInputStream("web/index.html");
code=status_code.OK;
}else{
this.out = new FileOutputStream("test"+rf);
type = mime("web"+rf);
File local = new File("web"+rf);
if(local.exists()){
page=new fileInputStream(local);
code=status_code.OK;
}
else{
page=errorpage;
code=status_code.NOT_FOUND;
}
}
reply(code,page,type);
}catch(IOException e){
System.out.println(e.getMessage());
}
}
void reply(status_code c,fileInputStream file,String type) throws IOException{
StringBuilder head = new StringBuilder();
head.append("HTTP/1.1 "+c.getCode()+" "+c+"\r\n");
head.append("Date: "+ new Date().toString()+"\r\n");
head.append("Server: Kilobyte MiniServer\r\n");
head.append("Connection: close\r\n");
head.append("Content-Type: "+type+" \r\n");
head.append("Content-length: "+file.available()+"\n\r");
head.append("\n\r");
int length=head.length();
for(byte b: head.toString().getBytes()){
this.response.write(b);
}
int pageBytes;
try{
while((pageBytes=file.read()) != -1){
this.response.write(pageBytes);
this.out.write(pageBytes);
}
file.close();
this.response.close();
this.request.close();
}catch(IOException e){
}
}
synchronized int incr(){
this.notifyAll();
return ++nRequest;
}
String mime(String file){
if(file.endsWith("css"))
return "text/css";
else if(file.endsWith("html"))
return "text/html";
else if(file.endsWith("js"))
return "text/javascript";
else if(file.endsWith("JPG"))
return "image/jpg";
else if(file.endsWith("jpg"))
return "image/jpg";
else if(file.endsWith("jpg"))
return "image/jpg";
else if(file.endsWith("png"))
return "image/png";
return "text";
}
}
class fileInputStream extends FileInputStream{
String f;
fileInputStream(String f) throws FileNotFoundException{
super(f) ;
this.f=f;
}
fileInputStream(File f) throws FileNotFoundException{
super(f);
this.f=f.toString();
}
#Override
public String toString(){
return f;
}
}
Can someone please resolve this issue.
Using JDK 1.8, I am trying to build a very simple chat application in Java using Sockets. In my client class as soon as following line executes
Message returnMessage = (Message) objectInputStream.readObject();
it throws exception.
Exception in thread "main" java.io.OptionalDataException
I am writing only objects of type Message to the stream and reading objects of type Message, since i wrote once, i dont think i am doing anything wrong in reading them in sequence.
Q. Also please let me know what is the best way to debug this type of application, how to hit the breakpoint in server while running client ?
Client
package com.company;
import sun.misc.SharedSecrets;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException{
Socket socket = new Socket("localhost", Server.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String readerInput = bufferedReader.readLine();
String[] readerInputTokens = readerInput.split("\u0020");
if(readerInputTokens.length != 2) {
System.out.println("Usage: Client <integer> <integer>");
} else {
Integer firstNumber = Integer.decode(readerInputTokens[0]);
Integer secondNumber = Integer.decode(readerInputTokens[1]);
Message message = new Message(firstNumber, secondNumber);
objectOutputStream.writeObject(message);
System.out.println("Reading Object .... ");
Message returnMessage = (Message) objectInputStream.readObject();
System.out.println(returnMessage.getResult());
socket.close();
}
}
public static boolean isInteger(String value) {
boolean returnValue = true;
try{Integer.parseInt(value);}
catch (Exception ex){ returnValue = false; }
return returnValue;
}
}
Server
package com.company;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public final static int PORT = 4446;
public static void main(String[] args) throws IOException, ClassNotFoundException {
new Server().runServer();
}
public void runServer() throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up & ready for connections ...");
// This while loop is necessary to make this server able to continuously in listning mode
// So that whenever a client tries to connect, it let it connect.
while (true){
Socket socket = serverSocket.accept(); // Server is ready to accept connectiosn;.
// Initialize Server Thread.
new ServerThread(socket).start();
}
}
}
Sever Thread
package com.company;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket socket = null;
ServerThread(Socket socket){
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeChars("\n");
objectOutputStream.flush();
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message message = (Message) objectInputStream.readObject();
multiplyNumbers(message);
System.out.println("Writing: "+message.toString());
objectOutputStream.writeObject(message);
System.out.println("Message Written");
socket.close();
} catch( IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
private void multiplyNumbers(Message message) {
message.setResult(message.getFirstNumber().intValue() * message.getSecondNumber().intValue());
}
}
Message Class
package com.company;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = -72233630512719664L;
Integer firstNumber = null;
Integer secondNumber = null;
Integer result = null;
public Message(Integer firstNumber, Integer secondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
}
public Integer getFirstNumber() {
return this.firstNumber;
}
public Integer getSecondNumber() {
return this.secondNumber;
}
public Integer getResult() {
return this.result;
}
public void setResult(Integer result) {
this.result = result;
}
#Override
public String toString() {
return "Message{" +
"firstNumber=" + firstNumber +
", secondNumber=" + secondNumber +
", result=" + result +
'}';
}
}
objectOutputStream.writeChars("\n");
Why are you writing a newline to an ObjectOutputStream? You're never reading it. Don't do that. Remove this wherever encountered.
I want to create a server that can accept multiple connections and then bind 2 clients as a pair and forward the data between these 2 clients. But it is about multiple pairs of clients. I already have multithread server that can create a new thread for each new connected client. The problem for me is that these threads dont know of each other and somehow I have to connect 2 clients to a connection pair.
For now I just create these pair connection as this: I wait for the first client, then I wait for the second client and then open a thread for the input of client 1 that gets forwarded to client 2 and the other way around. This is not usable for multiple clients.
How can I do this decent?
The way I see it, a client would need to
establish a TCP(?) connection with your server,
identify itself
give the ID of the other client it wishes to talk to
The first that connects would have to be kept on hold (in some global table in your server) until the second client connects.
Once a pair of clients would have been recognized as interlocutors, you would create a pair of threads to forward the data sent by each client to the other one.
UPDATE: Example
ClientSocket.java
package matchmaker;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientSocket implements Closeable {
private final Socket socket;
private final InputStream in;
private final OutputStream out;
private final String ownId;
private final String peerId;
public ClientSocket(Socket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
DataInputStream din = new DataInputStream(in);
this.ownId = din.readUTF();
this.peerId = din.readUTF();
}
public ClientSocket(String server, int port, String ownId, String peerId)
throws IOException {
this.socket = new Socket(server, port);
this.socket.setTcpNoDelay(true);
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.ownId = ownId;
this.peerId = peerId;
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF(ownId);
dout.writeUTF(peerId);
}
public String getOwnId() {
return ownId;
}
public String getPeerId() {
return peerId;
}
public InputStream getInputStream() {
return in;
}
public OutputStream getOutputStream() {
return out;
}
#Override
public void close() throws IOException {
socket.close();
}
}
Matchmaker.java: the server
package matchmaker;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Matchmaker extends Thread {
private static final Logger LOG
= Logger.getLogger(Matchmaker.class.getName());
private final int port;
private final Map<ClientPair,ClientSocket> waiting = new HashMap<>();
public static void main(String[] args) {
try {
int port = 1234;
int st = 0;
for (String arg: args) {
switch (st) {
case 0:
switch (arg) {
case "-p":
st = 1;
break;
default:
System.out.println("Unknown option: " + arg);
return;
}
break;
case 1:
port = Integer.parseInt(arg);
st = 0;
break;
}
}
Matchmaker server = new Matchmaker(port);
server.start();
server.join();
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private Matchmaker(int port) {
this.port = port;
setDaemon(true);
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(port);
while (true) {
ClientSocket socket = new ClientSocket(server.accept());
ClientPair pair = new ClientPair(
socket.getOwnId(), socket.getPeerId());
ClientSocket other;
synchronized(this) {
other = waiting.remove(pair.opposite());
if (other == null) {
waiting.put(pair, socket);
}
}
if (other != null) {
LOG.log(Level.INFO, "Establishing connection for {0}",
pair);
establishConnection(socket, other);
} else {
LOG.log(Level.INFO, "Waiting for counterpart {0}", pair);
}
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private void establishConnection(ClientSocket socket, ClientSocket other)
throws IOException {
Thread thread = new StreamCopier(
socket.getInputStream(), other.getOutputStream());
thread.start();
thread = new StreamCopier(
other.getInputStream(), socket.getOutputStream());
thread.start();
}
}
StreamCopier.java: a thread that reads from an InputStream and writes to an OutputStream
package matchmaker;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class StreamCopier extends Thread {
private static final Logger LOG
= Logger.getLogger(StreamCopier.class.getName());
private final InputStream in;
private final OutputStream out;
public StreamCopier(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
setDaemon(true);
}
#Override
public void run() {
LOG.info("Start stream copier");
try {
for (int b = in.read(); b != -1; b = in.read()) {
out.write(b);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
} finally {
LOG.info("End stream copier");
try {
out.close();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
}
ClientPair.java: a pair of client IDs
package matchmaker;
public class ClientPair {
private final String client1;
private final String client2;
public ClientPair(String client1, String client2) {
this.client1 = client1;
this.client2 = client2;
}
public String getClient1() {
return client1;
}
public String getClient2() {
return client2;
}
public ClientPair opposite() {
return new ClientPair(client2, client1);
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + client1.hashCode();
hash = 73 * hash + client2.hashCode();
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ClientPair other = (ClientPair) obj;
return client1.equals(other.client1) && client2.equals(other.client2);
}
#Override
public String toString() {
return "[" + client1 + "," + client2 + "]";
}
}
ReaderClient.java: a sample client that reads from the socket and writes to standard output
package matchmaker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReaderClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "reader", "writer")) {
Reader reader
= new InputStreamReader(client.getInputStream(), "UTF-8");
BufferedReader in = new BufferedReader(reader);
for (String s = in.readLine(); s != null; s = in.readLine()) {
System.out.println(s);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
WriterClient.java: a sample client that writes to the socket
package matchmaker;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WriterClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "writer", "reader")) {
Writer writer
= new OutputStreamWriter(client.getOutputStream(), "UTF-8");
PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < 30; ++i) {
out.println("Message line " + i);
}
out.flush();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
I am working on a homework which i have to send back and forth an object in serialized mode.I have a Client3.java file which sends an object to Server3.java.And Server3.java do the exact same thing.But when i try to read the object in Client3 he throws a java.io.IOException: Premature EOF error.From an extensive search i found that my program runs faster than the InputStream reading but i dont know how to fix this
here my 2 files
package server3;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
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);
//here we send an serialized object
Send obj = new Send();
ObjectOutputStream objOut = new
ObjectOutputStream(s.getOutputStream());
objOut.writeObject(obj);
/*********this is the chunk of code that makes the error*****************/
//here we read the serialized object
InputStream in = s.getInputStream();
ObjectInputStream ios = new ObjectInputStream(in);
SendResponse oin = (SendResponse) ios.readObject();
String gabim=oin.getGabim();
String gabimNr =oin.getGabimNr();
System.out.println(gabim);
System.out.println(gabimNr);
ios.close();
s.disconnect();
/***************************************************************************/
//catch all the possible errors
} catch (IOException ex) {
System.err.println("Gabim ne klient"+ex);
ex.printStackTrace();
}
}
}
class Send implements Serializable {
// the object to be send to the server
private static final long serialVersionUID = 1L;
int id = 1;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getPaid() {
return paid;
}
public void setPaid(int paid) {
this.paid = paid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
int amount = 2000;
int paid = 800;
String name = "Andi Domi";
}
And here it is the Server3.java file
package server3;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
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 {
//create the server
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 {
/*******we start to read the object send from the client here*******/
//create the sream
ObjectInputStream ios = new ObjectInputStream(t.getRequestBody());
//variables we need to connect to the database
final String url = "jdbc:mysql://localhost/httpServer";
final String user = "root";
final String password = "";
try {
//create the object to be read
Send oin = (Send) ios.readObject();
int id = oin.getId();
String emri = oin.getName();
int amount = oin.getAmount();
int paid = oin.getPaid();
//jdbc try
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, user,password);
//insert values into the first table
PreparedStatement s = con
.prepareStatement("INSERT INTO person(ID,Name,Amount,Paid) VALUES (?,?,?,?)");
s.setInt(1, id);
s.setString(2, emri);
s.setInt(3, amount);
s.setInt(4, paid);
s.executeUpdate();
//read the values from a table and add them to an array list
ResultSet rs = s.executeQuery("SELECT * from personat ORDER BY ID");
ArrayList<Personat> perList = new ArrayList<Personat>();
if (rs != null) {
while (rs.next()) {
Personat per = new Personat();
per.setID(rs.getInt("ID"));
per.setName(rs.getString("Name"));
per.setAmount(rs.getInt("Amount"));
perList.add(per);
}
}
//send the serialized object
String gabim="Ska asnje gabim";
String gabimNr="1";
t.sendResponseHeaders(200,0);
OutputStream os = t.getResponseBody();
SendResponse obj = new SendResponse(gabim,gabimNr,perList);
ObjectOutputStream objOut = new ObjectOutputStream(os);
objOut.writeObject(obj);
objOut.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
//ketu cojme nje object me keto te dhena
String gabim=("Dicka nuk shkoi mire me marrjen e objektit");
String gabimNr="3";
rrayList<Personat> perList = null;
t.sendResponseHeaders(200,0);
OutputStream os = t.getResponseBody();
SendResponse obj = new SendResponse(gabim,gabimNr,perList);
ObjectOutputStream objOut = new ObjectOutputStream(os);
objOut.writeObject(obj);
objOut.close();
} catch (SQLException e) {
//ketu cojme nje objekt me keto te dhena
e.printStackTrace();
String gabim=("Dicka nuk shkoi mire ne lidhje me databasin");
String gabimNr="4";
ArrayList<Personat> perList = null;
t.sendResponseHeaders(200,0);
OutputStream os = t.getResponseBody();
SendResponse obj = new SendResponse(gabim,gabimNr,perList);
ObjectOutputStream objOut = new ObjectOutputStream(os);
objOut.writeObject(obj);
objOut.close();
}
}
}
}
class Personat {
int ID;
String Name;
int Amount;
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getAmount() {
return Amount;
}
public void setAmount(int amount) {
Amount = amount;
}
}
class SendResponse implements Serializable {
private static final long serialVersionUID = 1L;
String gabim;
String gabimNr;
ArrayList<Personat> personList;
public SendResponse(String gabim, String gabimNr,
ArrayList<Personat> personList) {
super();
this.gabim = gabim;
this.gabimNr = gabimNr;
this.personList = personList;
}
public String getGabim() {
return gabim;
}
public void setGabim(String gabim) {
this.gabim = gabim;
}
public String getGabimNr() {
return gabimNr;
}
public void setGabimNr(String gabimNr) {
this.gabimNr = gabimNr;
}
public ArrayList<Personat> getPersonList() {
return personList;
}
public void setPersonList(ArrayList<Personat> personList) {
this.personList = personList;
}
}
after i run it from the ex.printStackTrace(); in the Client3 file i get this :
java.io.IOException: Premature EOF
java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(Unknown Source)
at sun.net.www.http.ChunkedInputStream.readAhead(Unknown Source)
at sun.net.www.http.ChunkedInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at server3.Client3.main(Client3.java:29)
i dont know hot to read the file faster or make my program slower ,do someone have any idea ?
I don't think it's due to the speed of your program, I would expect readObject() to block if there wasn't anything to read. Instead I think you are missing a terminator in the data you are trying to read, you need to take a look at the data that is being sent to your program. A similar issue was resolved here, though it is using readLine()