I am currently working on a project for sending/receiving objects through TCP sockets. I chose to work with the Kryo Serialization framework, since it is one of the most popular frameworks out there. I saw that for Network communication, KryoNet is recommended, but for my own reasons, I chose to use my own TCP Socket framework (mainly because I want custom control of TCP streams and Threads on my project). The problem I encounter is that I have created the following class for Messages:
public class MyMessage {
public HashMap<String, String> _values;
public MyMessage() {
_values = new HashMap<String, String>();
}
}
And on the server side I have the following code for reading input from a TCP Socket:
import java.io.*;
import java.net.*;
public class MyServer {
private ServerSocket _serverSocket;
private Integer _serverPort;
private boolean _killCommand;
public MyServer() {
_serverSocket = null;
_serverPort = -1;
try {
_serverSocket = new ServerSocket(0);
_serverPort = _serverSocket.getLocalPort();
System.out.println("server started on IP: " + _serverSocket.getInetAddress().getHostAddress() + ":" + _serverPort);
} catch (IOException e) {
e.printStackTrace();
}
_killCommand = false;
}
public void runServer() {
Socket _client= null;
while(_killCommand == false) {
try {
_client = _serverSocket.accept();
_out = _client.getOutputStream();
_in = _client.getInputStream();
(new Thread(new ServerThread(_in, _out))).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
the ServerThread class:
import java.io.*;
import java.util.HashMap;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.*;
public class ServerThread implements Runnable {
private InputStream _in;
private OutputStream _out;
private Kryo kryo;
private Input _input;
private Output _output;
public SynEFOthread(InputStream in, OutputStream out) {
_in = in;
_out = out;
kryo = new Kryo();
_output = new Output(_out);
_input = new Input(_in);
}
#Override
public void run() {
MyMessage msg = null;
System.out.println("Thread worker: about to parse input message");
msg = kryo.readObject(_input, MyMessage.class);
}
}
}
On the other side, the client code is the following:
import java.io.*;
import java.net.Socket;
import java.util.*;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.*;
public class MyClient {
public static void main(String[] args) throws Exception {
String server_ip = "";
Integer server_port = -1;
server_ip = args[0];
server_port = Integer.parseInt(args[1]);
Socket serverSocket = new Socket(server_ip, server_port);
OutputStream _out = serverSocket.getOutputStream();
InputStream _in = serverSocket.getInputStream();
Output _output = new Output(_out);
Input _input = new Input(_in);
MyMessage msg = new MyMessage();
msg._values = new HashMap<String, String>();
msg._values.put("TASK_TYPE", "TOPOLOGY");
Kryo kryo = new Kryo();
kryo.writeObject(_output, msg);
Thread.sleep(100);
kryo.writeObject(_output, _msg);
String _ack = kryo.readObject(_input, String.class);
serverSocket.close();
}
}
The problem is that on ServerThread.run() function, the kryo.readObject() call blocks and nothing is done after that. Am I doing something wrong? Am I opening the streams properly for use with the Kryo Serialization Framework?
Register your class with kryo.register(MyMessage.class) both on client and server sides.
Create a test for your serialization/deserialization code, but instead of sockets use ByteArrayOutputStream/ByteArrayInputStream.
Flush! After you write complete message to stream, flush written bytes to network: _output.flush()
Related
What I am trying to do here is create an application that will be a basic game, and first I have to get the networking functional. I'm struggling to send objects back and forth between server and client. The design I am trying to achieve is 2 processes with 2 threads each, the main thread and then a listener thread. I want the listener thread to listen for incoming objects, as this will be used for an event bus. Currently to get it working I'm using just a simple message class which holds a single string field called text. The issue I'm having is that the client listener thread doesn't seem to start, and the objects never get sent either way. Really struggling learning network programming here, any help is much appreciated.
Server side
package Server;
import java.net.*;
import java.util.List;
import Utilities.Message;
import java.io.*;
public class BattleshipServer
{
public static void executeThreadedServer(int port) throws Exception
{
ServerSocket server = new ServerSocket(port);
System.out.println("Awaiting connection");
Socket socket = server.accept();
System.out.println("Connection established");
BufferedReader kb = new BufferedReader(new InputStreamReader(System.in));
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
//Start the listener thread
ServerListener sListener = new ServerListener(kb, out, in);
sListener.run();
Message msg = new Message("temp");
while(!msg.getText().equalsIgnoreCase("exit"))
{
msg = new Message(kb.readLine());
out.writeObject(msg);
out.flush();
}
}
}
------------------------------------------------------------------------------------------------------------
package Server;
import java.io.BufferedReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import Utilities.Message;
public class ServerListener implements Runnable
{
private BufferedReader keyBoard;
private ObjectOutputStream out;
private ObjectInputStream in;
public ServerListener(BufferedReader keyboard, ObjectOutputStream out, ObjectInputStream in)
{
this.keyBoard = keyboard;
this.out = out;
this.in = in;
}
#Override
public void run()
{
System.out.println("Server listener started");
try {
while(true)
{
Message msg;
while((msg = (Message)this.in.readObject()) != null)
{
System.out.println(msg.getText());
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Client Side
package Client;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import Utilities.Message;
import java.io.*;
public class BattleshipClient
{
public static void executeThreadedClient(String address, int port) throws Exception
{
Socket socket = new Socket(address, port);
BufferedReader kb = new BufferedReader(new InputStreamReader(System.in));
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ClientListener cListener = new ClientListener(kb,out,in);
cListener.run();
Message msg = new Message("temp");
while(!msg.getText().equalsIgnoreCase("exit"))
{
msg = new Message(kb.readLine());
out.writeObject(msg);
out.flush();
}
socket.close();
}
}
------------------------------------------------------------------------------------------------------------
package Client;
import java.io.BufferedReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import Utilities.Message;
public class ClientListener implements Runnable
{
private BufferedReader keyBoard;
private ObjectOutputStream out;
private ObjectInputStream in;
public ClientListener(BufferedReader keyboard, ObjectOutputStream out, ObjectInputStream in)
{
this.keyBoard = keyboard;
this.out = out;
this.in = in;
}
#Override
public void run()
{
System.out.println("Client listener started");
try
{
while(true)
{
Message msg = (Message)in.readObject();
System.out.println(msg.getText());
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Although your ClientListener and ServerListeners are implementing Runnable, they are not run in a separate thread. In your implementation, it is just another function call and therefore the code after the listener.run() never gets called.
So instead of doing:
ClientListener cListener = new ClientListener(kb,out,in);
cListener.run();
You need to do something like:
Thread clientThread = new Thread(new ClientListener(kb,out,in));
clientThread.start();
And on the server side you need to do something similar.
Im having Spring Boot Application for communication between Machines (tcp Clients) and TCP Server (localhost). I am able to communicate with one machine/client, but I cant communicate with 2 or more machines.
Therefore I start my Spring Boot Application:
package com.example.workflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
#SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
Runnable serverZyklisch = new ServerZyklisch();
Runnable serverAzyklisch = new ServerAzyklisch();
for (int i = 0; i < 4; i++) {
new Thread(serverZyklisch).start();
new Thread(serverAzyklisch).start();
}
SpringApplication.run(Application.class);
}
}
There I have different Threads started, so that the clients (for example 10.50.12.174 = Press, 10.50.12.204 = Drill) can connect to TCP Server over Socket Connection.
My ServerAzyklisch class is like this:
package com.example.workflow;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerAzyklisch implements Runnable, JavaDelegate {
int count = 0;
private final ServerSocket ssocket;
static String param = StartTCPServersDelegate.parameter;
HexToByteConverter hexToByteConverter = new HexToByteConverter();
// 2 TCP Server starten Port 2000, Port 2001
public ServerAzyklisch(String Pparam) throws IOException {
ssocket = new ServerSocket(2000);
param = Pparam;
}
public ServerAzyklisch() throws IOException {
ssocket = new ServerSocket(2000);
}
public void run() {
byte[] buf = new byte[1];
System.out.println(param+"Paraaam");
InputStream in;
OutputStream out = null;
Socket socket = null;
//Thread immer aktiv
int n = 0;
while(true){
try {
// Wartet auf Socket Verbindung
System.out.println("Server is listening on port "+ ssocket.getLocalPort());
socket = ssocket.accept();
count++;
System.out.println("Countet clients: "+count);
socket.setSoLinger(true, 1000);
System.out.println("Sockeport: "+socket.getLocalPort());
System.out.println("Connection from " + socket.getInetAddress().toString());
//Inputstream
in = socket.getInputStream();
//Outputstream
out = socket.getOutputStream();
//Datenpuffer deklarieren (anlegen)
byte []data = new byte[132];
byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000006e0000000000000000000000000001000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"+param);
byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
in.read(buf);
while (buf[0] != -1) {
out.write(Pressen1hexdump110);
out.write(Pressen2hexdump);
out.write(Pressen3hexdump);
}
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void execute(DelegateExecution delegateExecution) throws IOException {
}
}
Now I want to outsource the "while loop" (with out.write) in other Classes to use the connection to Socket like in ServerAzyklisch run method.
Therefore I wrote for example a Class Presse.java
package com.example.workflow;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Presse implements JavaDelegate {
ServerSocket ssocket;
private HexToByteConverter hexToByteConverter = new HexToByteConverter();
Socket socket;
InputStream in;
OutputStream out;
byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000006e00000000000000000000000000010000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005");
byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
public Presse() throws IOException {
ssocket = new ServerSocket(2000);
socket = ssocket.accept();
//Inputstream
in = socket.getInputStream();
//Outputstream
out = socket.getOutputStream();
}
public void sendMessage(InputStream in, OutputStream out, byte[]message) throws IOException {
out.write(Pressen1hexdump110);
out.write(Pressen2hexdump);
out.write(Pressen3hexdump);
socket.close();
}
#Override
public void execute(DelegateExecution delegateExecution) throws Exception {
PostRequestDelegate postRequestDelegate = new PostRequestDelegate();
postRequestDelegate.post();
}
}
I want to send my 3 messages from this class, like in ServerAzyklisch class. But it throws Error because:
Caused by: java.net.BindException: Address already in use: NET_Bind
I know this because is I do Socket.accept a second time, but I dont understand how I can achieve this to work. Do I have to close socket connection ? If yes where and with which Java Command ?
If you want to have more than one instances of "Presse" in your program, the very least you'll need to remove ServerSocket from it. Instead, you should accept the connection from the client somewhere else, and pass the client socket to the Presse constructor:
public Presse(Socket clientSocket) throws IOException {
this.socket = clientSocket;
//Inputstream
in = socket.getInputStream();
//Outputstream
out = socket.getOutputStream();
}
Usually you want to create only one ServerSocket, and call accept on it in a loop. To allow more than one client to connect at a time, communicate with the client in a separate thread. This way the server can go and accept a new connection. Here's a skeleton example of how to use a thread pool for this:
int maxClients = 10;
ExecutorService threadPool = Executors.newFixedThreadPool(maxClients);
ServerSocket serverSocket = new ServerSocket(2000);
while (true) {
Socket clientSocket = serverSocket.accept();
threadPool.submit(() -> {
// Communicate with clientSocket, for example:
Presse p = new Presse(clientSocket);
// You'll want to have this code in a separate method
});
}
What I'm trying to do is make receiver class in the server which receives the sent messages from the client and make a sender class in the client. I'm trying to make the receiver in the server first 'cause I'll probably figure out how to do that in the client side after learning it. But doing this gives me java.net.BindException: Address already in use: JVM_Bind. I think it's because I have another Server server = new Server(); in the receiver. How do I solve this?
Server.java
package MultithreadingServerClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
ServerSocket serverSocket = new ServerSocket(3000);
Socket socket = serverSocket.accept();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
public Server() throws IOException {
}
public static void main(String[] args) {
Thread serverSender = new Thread(new ServerSender());
Thread serverReceiver = new Thread(new ServerReceiver());
serverSender.start();
serverReceiver.start();
}
}
// Sender class
class ServerSender implements Runnable {
#Override
public void run() {
try {
Server serve = new Server();
Scanner scanner = new Scanner(System.in);
String msg = "";
while (!msg.equalsIgnoreCase("exit")) {
System.out.print("Server: ");
msg = scanner.nextLine();
serve.printWriter.println(msg);
}
} catch (IOException e) {
System.err.println("Sender Error " + e);
}
}
}
class ServerReceiver implements Runnable {
#Override
public void run() {
try {
Server server = new Server();
System.out.println(server.bufferedReader.readLine());
} catch (IOException e) {
System.err.println("Receiver Error " + e);
}
}
}
Client.java
package MultithreadingServerClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
Socket socket = new Socket("localhost", 3000);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
public Client() throws IOException {
}
// Receive messages
public static void main(String[] args) {
try {
Client client = new Client();
while (true) {
System.out.println("Server: " + client.bufferedReader.readLine());
}
} catch (IOException e) {
System.out.println("Server Closed!");
}
}
}
class ClientSender implements Runnable {
#Override
public void run() {
try {
Client client = new Client();
client.printWriter.println("Test message: send to Server");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Don't create multiple instances of Server, you may create the instance in main then just pass the bufferedReader to the receiver class, and the printWriter to the sender class.
Sender class :
class ServerSender implements Runnable {
private PrintWriter writer;
public ServerSender(PrintWriter printWriter){
writer = printWriter;
}
#Override
public void run() {
try {
Scanner scanner = new Scanner(System.in);
String msg = "";
while (!msg.equalsIgnoreCase("exit")) {
System.out.print("Server: ");
msg = scanner.nextLine();
writer.println(msg);
}
} catch (IOException e) {
System.err.println("Sender Error " + e);
}
}
}
Receiver class :
class ServerReceiver implements Runnable {
private BufferedReader reader;
public ServerReceiver(BufferedReader bufferedReader){
reader = bufferedReader;
}
#Override
public void run() {
try {
System.out.println(reader.readLine());
} catch (IOException e) {
System.err.println("Receiver Error " + e);
}
}
}
Method main in Server :
public static void main(String[] args) {
Server serve = new Server();
Thread serverSender = new Thread(new ServerSender(serve.printWriter));
Thread serverReceiver = new Thread(new ServerReceiver(serve.bufferedReader));
serverSender.start();
serverReceiver.start();
}
You have two threads starting a new instance of the connection at the same port (3000). I assume that you are trying to have one thread receive a message from a server and another one for sending a message to client. I don't think you need to have a design like this. This can be done in a single threaded environment. There is no need for client (sender & receiver) and server (sender & receiver).
ServerSocket.accept(); method will listen to all the message incoming to the specified port number.
In order for the server to send reply to the client . You can use
DataOutputStream.writeUTF() & DataOutputStream.flush() method.
The same goes for client side. Have a look at the program below.
class Server {
public static void main(String args[]) throws IOException {
try (ServerSocket serverSocket = new ServerSocket(3333); // open connection at port 3333
Socket socket = serverSocket.accept();
DataInputStream inputStream = new DataInputStream(socket.getInputStream());) {
DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String messageFromClient = "", messageToBeClient = "";
while (!messageFromClient.equals("exit")) {
messageFromClient = inputStream.readUTF();
System.out.println("Message From Client : " + messageFromClient);
messageToBeClient = reader.readLine();
outStream.writeUTF(messageToBeClient);
outStream.flush();
}
}
}
}
class Client {
public static void main(String args[]) throws Exception {
try (Socket socket = new Socket("localhost", 3333); // establish connection to the open socket at port 3333
DataInputStream inputStream = new DataInputStream(socket.getInputStream());) {
DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String messageFromServer = "", messageToServer = "";
while (!messageToServer.equals("exit")) {
messageToServer = reader.readLine();
outStream.writeUTF(messageToServer);
outStream.flush();
messageFromServer = inputStream.readUTF();
System.out.println("Message From Server : " + messageFromServer);
}
}
}
}
How do I keep the server "open" so that it can send and receive objects on a continuing basis without crashing? Basically, I would like to put an infinite loop around the readRecord method, so that it runs indefinitely.
server:
package net.bounceme.dur.driver;
import java.net.*;
import java.io.*;
import java.util.Properties;
import java.util.logging.Logger;
public class Server {
private static final Logger log = Logger.getLogger(Server.class.getName());
private final RecordQueue recordsQueue = new RecordQueue();
public static void main(String[] args) throws IOException {
Properties props = PropertiesReader.getProps();
int portNumber = Integer.parseInt(props.getProperty("port"));
new Server().readRecord(portNumber);
}
public void readRecord(int portNumber) throws IOException {
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket socket = serverSocket.accept();
ObjectOutputStream objectOutputStream = null;
MyRecord recordFromClient = null;
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
while (true) {
try {
recordFromClient = (MyRecord) objectInputStream.readObject();
} catch (ClassNotFoundException e) {
System.out.println(e);
}
objectOutputStream.writeObject(recordFromClient);
}
}
}
client:
package net.bounceme.dur.driver;
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class Client {
private List<MyRecord> iterate() {
MyRecord myRecord = null;
List<MyRecord> records = new ArrayList<>();
for (int i = 0; i < 9; i++) {
myRecord = new MyRecord(i, "foo");
records.add(myRecord);
}
return records;
}
public void simple(String server, int portNumber) throws IOException, ClassNotFoundException {
Socket s = new Socket(server, portNumber);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
List<MyRecord> records = iterate();
for (MyRecord record : records) {
oos.writeObject(record);
}
oos.flush();
Object received = ois.readObject();
System.out.println(received);
oos.close();
ois.close();
}
public static void main(String args[]) throws IOException, ClassNotFoundException {
Properties props = PropertiesReader.getProps();
int portNumber = Integer.parseInt(props.getProperty("port"));
String server = (props.getProperty("server"));
new Client().simple(server, portNumber);
}
}
server output:
thufir#dur:~$
thufir#dur:~$ java -jar NetBeansProjects/Server/dist/Server.jar
Exception in thread "main" java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1876)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1785)
at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1285)
at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1230)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1426)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1576)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:350)
at net.bounceme.dur.driver.Server.readRecord(Server.java:32)
at net.bounceme.dur.driver.Server.main(Server.java:16)
thufir#dur:~$
client output:
thufir#dur:~$
thufir#dur:~$ java -jar NetBeansProjects/Client/dist/Client.jar
value=0, id='foo
thufir#dur:~$
Okay what your problem is, your server was made to only read and handle one object at a time. So When you client tries to send all of those MyRecord objects, the server reads one, and then tries to send it back to you, the problem is, you are still trying to send the other MyRecord objects while the server is trying to send you the FIRST MyRecord object. Client/Server connections are like a game of tennis. One person must serve the ball to the other player, and the other must then hit the ball back. You cannot both hit a ball with neither of you recieving.
So in,
for (MyRecord record : records) {
oos.writeObject(record);
}
oos.flush();
Object received = ois.readObject();
System.out.println(received);
you should put the
oos.flush();
Object received = ois.readObject();
System.out.println(received);
inside of the for() loop, that way each MyRecord object is sent to the server, read by the server, sent back to the client by the server, and read by the client.
Final result:
for (MyRecord record : records) {
oos.writeObject(record);
oos.flush();
Object received = ois.readObject();
System.out.println(received);
}
See the changes(i edited some code to run on my machine, so make your changes appropriately)
import java.net.*;
import java.io.*;
import java.util.Properties;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.List;
class MyRecord implements java.io.Serializable
{
int x;
String y;
MyRecord(int a,String b)
{
x=a;
y=b;
}
}
class Server {
private static final Logger log = Logger.getLogger(Server.class.getName());
//private final RecordQueue recordsQueue = new RecordQueue();
public static void main(String[] args) throws IOException {
//Properties props = PropertiesReader.getProps();
//int portNumber = Integer.parseInt(props.getProperty("port"));
new Server().readRecord(2*1000);
}
public void readRecord(int portNumber) throws IOException {
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket socket = serverSocket.accept();
ObjectOutputStream objectOutputStream = null;
MyRecord recordFromClient = null;
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
while (true) {
try {
recordFromClient = (MyRecord) objectInputStream.readObject();
if(recordFromClient.x==-1) {break;}
} catch (ClassNotFoundException e) {
System.out.println(e);
}
objectOutputStream.writeObject(recordFromClient);
objectOutputStream.flush();
}
}
}
class Client {
private List<MyRecord> iterate() {
MyRecord myRecord = null;
List<MyRecord> records = new ArrayList<>();
for (int i = 0; i < 9; i++) {
myRecord = new MyRecord(i, "foo");
records.add(myRecord);
}
return records;
}
public void simple(String server, int portNumber) throws IOException, ClassNotFoundException {
Socket s = new Socket(server, portNumber);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
List<MyRecord> records = iterate();
for (MyRecord record : records) {
oos.writeObject(record);
oos.flush();
Object received = ois.readObject();
System.out.println(received);
}
MyRecord record= new MyRecord(-1,"end");
oos.writeObject(record);
oos.flush();
oos.close();
ois.close();
}
public static void main(String args[]) throws IOException, ClassNotFoundException {
//Properties props = PropertiesReader.getProps();
//int portNumber = Integer.parseInt(props.getProperty("port"));
String server = "localhost";
new Client().simple(server, 2000);
}
}
This works to a degree:
package net.bounceme.dur.driver;
//import stuff
public class Server {
private static final Logger log = Logger.getLogger(Server.class.getName());
private final RecordQueue recordsQueue = new RecordQueue();
public static void main(String[] args) {
Properties props = PropertiesReader.getProps();
int portNumber = Integer.parseInt(props.getProperty("port"));
while (true) {
try {
new Server().inOut(portNumber);
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Server.class.getName()).log(Level.FINE, null, ex);
}
}
}
private List<MyRecord> dummyRecords() {
MyRecord record = null;
List<MyRecord> records = new ArrayList<>();
for (int i = 0; i < 9; i++) {
record = new MyRecord(i, "foo");
records.add(record);
log.info(record.toString());
}
return records;
}
public void inOut(int portNumber) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket socket = serverSocket.accept();
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
log.info("...connected...waiting for data...");
MyRecord recordFromClient = (MyRecord) objectInputStream.readObject();
objectOutputStream.writeObject(recordFromClient);
objectOutputStream.flush();
objectInputStream.close();
objectOutputStream.close();
log.info(recordFromClient.toString());//never logs
System.out.println("never gets here");
}
}
except that it never logs the recordFromClient, which is kind of important. On the plus side, it doesn't crash.
Hey I am implementing an electronic voting system based on client server chat.
When I run the server it runs without any problems but without printing as well and also the client. But as soon as I give the input to the client, it gives me the following exception and crashes. Here is the code of the server and the client. So what do u think I should do to start the engine?
package engine;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
public class Server {
ServerSocket server;
int port = 6000;
public Server() {
try {
server = new ServerSocket(6000);
} catch (IOException e) {
e.printStackTrace();
}
}
public void handleConnection(){
try {
while(true){
Socket connectionSocket;
connectionSocket = server.accept();
new ConnectionHandler(connectionSocket);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.handleConnection();
}
}
class ConnectionHandler implements Runnable {
Socket connectionSocket;
Calendar votingStartTime;
Calendar votingEndTime;
boolean timeUp;
ObjectInputStream inFromClient;
ObjectOutputStream outToClient;
BufferedWriter outToFile;
BufferedReader inFromAdmin;
ArrayList<SingleClient> clients = new ArrayList<SingleClient>();
ArrayList<Candidate> candidates;
this is the part of the code the Exception comes from:
public ConnectionHandler(Socket socket) {
try {
this.connectionSocket = socket;
votingStartTime = new GregorianCalendar();
outToClient = new ObjectOutputStream(
connectionSocket.getOutputStream());
inFromClient = new ObjectInputStream(
connectionSocket.getInputStream());
inFromAdmin = new BufferedReader(new InputStreamReader(System.in));
startVotingSession();
Thread t = new Thread(this);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
and this is the client's main method the Exception as soon as i give the input:
public static void main(String[] args) throws Exception {
client c = new client();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input;
while(true){
input = br.readLine();
if(input.equals("0")){
c.register();
}else if(input.equals("1")){
c.login();
}else if(input.equals("2")){
c.listCandidates();
}else if(input.equals("3")){
c.vote();
}else if(input.equals("4")){
c.checkResults();
}else if(input.equals("5")){
c.checkFinalResults();
}else if(input.equals("6")){
c.logout();
}else {
break;
}
}
}
}
without seeing the relevant code, i would guess you are recreating the ObjectInputStream on an existing socket InputStream. you must create the object streams once per socket and re-use them until you are completely finished with the socket connection. also, you should always flush the ObjectOutputStream immediately after creation to avoid deadlock.