So I send a Server object to a client with this thread:
public ConnectionThread(final Server server) {
super(new Runnable() {
public void run() {
try {
Socket client = server.serverSocket.accept();
server.clients.add(client);
ObjectInputStream in = new ObjectInputStream(
client.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(
client.getOutputStream());
System.out.println("Connected client: "
+ client.getRemoteSocketAddress());
server.launchNewThread();
Object input;
while (!client.isClosed()) {
input = in.readObject();
if (input != null) {
if (input.toString().equals("server")) {
out.writeObject(server);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
And when I call out.writeObject(server) I get this exception:
java.io.NotSerializableException: java.net.Socket
Here is the Server class:
public class Server implements Serializable {
private static final long serialVersionUID = 4634111951586948020L;
public ServerArgs args;
public ArrayList<Socket> clients = new ArrayList<Socket>();
public ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
launchNewThread();
}
public void launchNewThread() {
ConnectionThread thread = new ConnectionThread(this);
thread.start();
}
public static void main(String[] args) throws IOException {
new Server(27015);
}
}
public ArrayList<Socket> clients = new ArrayList<Socket>();
public ServerSocket serverSocket;
You have plenty of non-serializable sockets right there. It's very unclear what the purpose of "sending a server" is, but perhaps you should either just send the ServerArgs or mark those two fields transient.
Related
I'm developing a client-server app, and my server can receive connection requests from 2 types of clients, therefore I instanciate the ObjectInputStream directly in my server, to recognize the client type (client or worker) and then I have a Thread for each type of client.
While initializing the thread, I pass as an argument the socket which I created in the server. (code below)
public class Server {
public int PORT;
private ArrayList<DealWithClient> connectedClients;
private ArrayList<DealWithWorker> connectedWorkers;
private ArrayList<String> types = new ArrayList<>();
private BlockingQueue<Runnable> tasks = new BlockingQueue<>();
private SearchTypes searchTypes;
private ObjectOutputStream out;
private ObjectInputStream in;
public static void main(String[] args) {
new Server(args[0]);
}
public Server(String port) {
this.PORT = Integer.parseInt(port);
startServing();
}
public void startServing() {
connectedClients = new ArrayList<>();
connectedWorkers = new ArrayList<>();
try {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Lançou ServerSocket: " + s);
try {
while (true) {
Socket socket = s.accept();
inscription(socket);
}
} finally {
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void inscription(Socket socket) {
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
Object obj = in.readObject();
if(obj instanceof String) {
String inscriptionMessage = (String) obj;
System.out.println("Mensagem recebida: " + obj);
if(inscriptionMessage.contains("Inscrição cliente")) {
DealWithClient dwc = new DealWithClient(socket, this);
dwc.start();
addClient(dwc);
out.writeObject(searchTypes);
}
if(inscriptionMessage.contains("Inscrição worker")) {
String[] worker = inscriptionMessage.split(" ");
searchTypes = new SearchTypes(worker[4]);
DealWithWorker dww = new DealWithWorker(socket, this);
dww.start();
addWorker(dww);
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
public void addClient(DealWithClient client) {
connectedClients.add(client);
System.out.println("Cliente adicionado! »» " + client.toString());
}
public void addWorker(DealWithWorker worker) {
connectedWorkers.add(worker);
System.out.println("Worker adicionado! »» " + worker.toString());
}
My DealWithClient code below, is where I'm having the problem, since that I can not reach the System.out.println("BBB"), because it gets stuck in the instanciation of ObjectInputStream.
public class DealWithClient extends Thread{
private Socket socket;
private Server server;
private ObjectInputStream in;
private ObjectOutputStream out;
private Client client;
public DealWithClient(Socket socket, Server server) {
this.server = server;
this.socket = socket;
}
#Override
public void run() {
try {
connectToServer();
} catch (IOException e) {
e.printStackTrace();
}
while(!interrupted()) {
treatClientRequests();
}
}
private void connectToServer() throws IOException {
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("AAA");
in = new ObjectInputStream(socket.getInputStream());
System.out.println("BBB");
}
I've looked for similar questions around here, but I didn't managed to find one that could solve my issue.
My question is, once I instanciate the ObjectInput and ObjectOutput streams in the server, I cannot do it again inside my Thread?
Thanks!
You are most likely getting a deadlock error because the socket is still being used by ObjectOutputStream when you are trying to get an Input stream from the same socket. Try calling the close() method on out before instantiating the ObjectInputStream below. Calling the close() method will free up resources.
This question already has an answer here:
ObjectInputStream(socket.getInputStream()); does not work
(1 answer)
Closed 7 years ago.
I'm doing a simple echo chat and server, but methods send and receive in class Connection don't work with ObjectInputStream and ObjectOutputStream, but with PrintWriter and BufferedReader work fine.
Now I'm trying to understand the serialization using sockets, help me to understand why this code does not work:
Client
public class Client {
private Connection connection;
private String getServerAddress() {
return "localhost";
}
private int getServerPort() {
return 4444;
}
public void run() {
BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
try {
connection = new Connection(new Socket(getServerAddress(), getServerPort()));
SocketThread socketThread = new SocketThread();
socketThread.setDaemon(true);
socketThread.start();
while (true) {
String text = bis.readLine();
if (text.equalsIgnoreCase("exit"))
break;
connection.send(text);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
client.run();
}
public class SocketThread extends Thread {
#Override
public void run() {
try {
while (true) {
String message = connection.receive();
System.out.println(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Connection
public class Connection implements Closeable {
private final Socket socket;
private final ObjectInputStream in;
private final ObjectOutputStream out;
public Connection(Socket socket) throws Exception {
this.socket = socket;
this.in = new ObjectInputStream(socket.getInputStream());
this.out = new ObjectOutputStream(socket.getOutputStream());
}
public void send(String message) throws Exception {
out.writeObject(message);
}
public String receive() throws Exception {
return (String) in.readObject();
}
#Override
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
}
Server
public class Server {
public static void main(String[] args) {
int port = 4444;
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (true) {
Socket socket = serverSocket.accept();
new Handler(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static class Handler extends Thread {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try (Connection connection = new Connection(socket)) {
while (true) {
String message = connection.receive();
if (message.equals("exit"))
break;
System.out.println(message);
connection.send("Echo: " + message);
}
} catch (Exception e) {
}
}
}
}
This is because ObjectInputStream blocks trying to read the stream header written by an ObjectOutputStream in its constructor, and you are creating both of your input streams before the output streams. You can solve this by switching the order that you create the object streams in:
this.out = new ObjectOutputStream(socket.getOutputStream());
this.in = new ObjectInputStream(socket.getInputStream());
The javadoc for the ObjectOutputStream constructor also notes that you might want to flush the stream after creating it to ensure the header is sent.
I have a server and a client the client already connects successfully to the server even if i start another client it connects successfully and here is my problem the clients can send data to the server (its basically only a string)the server gets the data of both clients but the clients only get their own data back and i would like to have that both clients get the same data from the server back.
Server:
public class Server extends Application {
#Override
public void start(Stage primaryStage) {
}
static ServerSocket serverSocket;
static Socket socket;
static DataOutputStream out;
static DataInputStream in;
static Users[] user = new Users[10];
public static void main(String[] args) throws IOException {
System.out.println("Starting server...");
serverSocket = new ServerSocket(7777);
System.out.println("Server started");
while(true){
socket = serverSocket.accept();
for(int i = 0;i < 10; i++){
System.out.println("Connection from:" + socket.getInetAddress());
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
if(user[i] == null){
user[i] = new Users(out,in,user);
Thread thread = new Thread(user[i]);
thread.start();
break;
}
}
}
}
private static class Users implements Runnable{
DataOutputStream out;
DataInputStream in;
Users[] user = new Users[10];
String name;
public Users(DataOutputStream out,DataInputStream in,Users[] user){
this.out = out;
this.in = in;
this.user = user;
}
#Override
public void run() {
while(true){
try {
String recievingData = in.readUTF();
System.out.println(recievingData);
out.writeUTF(recievingData);
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}}}
Client(both are the same):
public class ServerClient {
static Socket socket;
static DataInputStream in;
static DataOutputStream out;
public ServerClient() throws IOException{
System.out.println("Connecting");
socket = new Socket("localhost",7777);
System.out.println("Connecting succesful");
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
System.out.println("Recieving");
Input input = new Input(in);
Thread thread = new Thread(input);
thread.start();
}
public static void UploadPos(){
try {
out.writeUTF("TEST");
} catch (IOException ex) {
Logger.getLogger(ServerClient.class.getName()).log(Level.SEVERE, null, ex);
}
}}
class Input implements Runnable{
DataOutputStream out;
DataInputStream in;
public Input(DataInputStream in){
this.in = in;
}
#Override
public void run() {
while(true){
try {
String data = in.readUTF();
System.out.println(data);
} catch (IOException ex) {
Logger.getLogger(Input.class.getName()).log(Level.SEVERE, null, ex);
}
}
}}
Create a list of output streams.
List<DataOutputStream> clientOuts = new ArrayList<>();
after
out = new DataOutputStream(socket.getOutputStream());
add
clientOuts.add(out);
then replace
out.writeUTF(recievingData);
with
for(DataOutputStream cout :clientOutputs) {
cout.writeUTF(recievingData);
}
So I have a client:
public class TalkClient extends Thread
{
private int port;
private String host;
DocCntl theDocCntl;
public TalkClient(String host, int port) throws IOException
{
this.host = host;
this.port = port;
theDocCntl = new DocCntl(this);
}
public void run()
{
try
{
System.out.println("Seeking connection...");
Socket socket = new Socket(host, port);
DataInputStream in = new DataInputStream(socket.getInputStream());
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
}catch(IOException e)
{
e.printStackTrace();
}
}
public static void main(String [] args)
{
int port = 5050;
try
{
Thread t = new TalkClient("127.0.0.1", port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
public void pushToServer(){
String theData = this.theDocCntl.theDoc.docTA.getText();
}
}
And I have a server:
public class TalkServer extends Thread
{
private ServerSocket serverSocket;
public static DocCntl theCntl;
public TalkServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
}
public void run()
{
try
{
System.out.println("Listening for connections...");
Socket client = serverSocket.accept();
DataInputStream in = new DataInputStream(client.getInputStream());
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
DataOutputStream out = new DataOutputStream(client.getOutputStream());
}catch(IOException e)
{
e.printStackTrace();
}
}
public static void main(String [] args)
{
int port = 5050;
try
{
Thread t = new TalkServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
In the client, I have a method called pushToServer, which I want to take the String data from a textArea on the client, and then push that to all the other connected clients. But I'm not sure how to handle sending the message to each individual connected client through the sockets. I've given it some thought, and I think I need to do 3 things:
1) Create and maintain a list of connected clients(threads). In the server class itself? Or in another class?
2) On the server, have some means of 'catching' the String data from one client, and then pushing it to all the other clients. This is why(I think) I need the list of clients. If I can figure out how to catch this(maybe through the input stream?) and then iterate through the list of clients to their text areas.
3) On the client side, I need to be able to catch the string from the server.
Any help on these 3 things would be greatly appreciated.
I want to send multiple data type over socket.
I have that code:
when I create client, it generates public and private keys and sends the public to serve and the serve stores it.
when client wants to send message to another client, it gets his public key from the server to encrypt the message.
But when I run this code it freeze at client in dest_public_key=(PublicKey) oin.readObject()
Why it stop at here?
Why it doesn't read the PublicKey's object that the handler writes to it?
Is there any problems in streams?
public class Server {
private static final int PORT = 9001;
ServerSocket listener;
private Handler h[] = new Handler[5];
public PublicKey[] keys = new PublicKey[5];
private int clientCount = 0;
public Server() throws Exception{
System.out.println("The server is running.");
listener = new ServerSocket(PORT);
run();
}
public void run() throws Exception{
System.out.println("Waiting for a client ...");
while (true) { addClient(listener.accept());}
}
private void addClient(Socket socket) throws Exception{
h[clientCount] = new ServerHandler(this, socket,clientCount);
h[clientCount].open(clientCount);
h[clientCount].start();
clientCount++;
}
public void store(int id,PublicKey key){
keys[id]=key;}
public PublicKey getPublicKey(int id){
return keys[id]; }
public static void main(String[] args) throws Exception {
Server s = new Server();}
}
handle class
public class Handler extends Thread {
private Server server;
private Socket socket;
private int ID = -1;
private DataInputStream streamIn = null;
private DataOutputStream streamOut = null;
private ObjectInputStream obIn = null;
private ObjectOutputStream obOut = null;
public Handler(Server _server, Socket _socket, int i){
super();
server = _server;
socket = _socket;
ID = i;
}
public void run()
{ while (true)
{ try
{
int dest=streamIn.readInt();
PublicKey dest_public_key=server.getPublicKey(dest);
obOut.writeObject(dest_public_key);
obOut.flush();}}
}
public void open(int i)
{
PublicKey publick = null;
try {
streamOut = new DataOutputStream(socket.getOutputStream());
streamIn = new DataInputStream(socket.getInputStream());
obOut = new ObjectOutputStream(socket.getOutputStream());
obIn = new ObjectInputStream(socket.getInputStream());
publick=(PublicKey)obIn.readObject();
server.store(ID,publick);
streamOut.writeInt(i);
streamOut.flush();
} catch (Exception e) {
e.printStackTrace();}
}}
client class
public class Client extends implements Runnable {
DataInputStream din;
DataOutputStream dot;
ObjectInputStream oin;
ObjectOutputStream oot;
public Client() {
try {
socket = new Socket(serverAddress, 9001);
din = new DataInputStream(socket.getInputStream());
dot = new DataOutputStream(socket.getOutputStream());
oot = new ObjectOutputStream(socket.getOutputStream());
oin = new ObjectInputStream(socket.getInputStream());
RSA.generateKey();
public_key=RSA.keys.getPublic();
private_key=RSA.keys.getPrivate();
oot.writeObject(public_key);
oot.flush();
int j =din.readInt(); // read number from server
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Client client = new Client();
PublicKey dest_public_key=null;
System.out.println("enter client that you would to send to it");
Scanner input = new Scanner( System.in );
int select = input.nextInt();
dot.writeInt(select);
dot.flush();
dest_public_key=(PublicKey) oin.readObject();
}
}