ObjectInputStream DeadLock - java

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.

Related

Java - establish a chat between two clients

Im trying to code a simple server that creates a chat between any two clients that connect to the server. (for any two new clients the server will open a new chat thred/s and then will wait to the next two clients)
i have tried the followןng solution:
Server:
public class Server
{
public Server() throws IOException
{
ServerSocket sc = new ServerSocket(7777);
Socket s1, s2;
while(true)
{
s1 = sc.accept();
s2 = sc.accept();
new ServerThread(s1, s2).start();
new ServerThread(s2, s1).start();
}
}
}
Server threads (two threads as explained in the comment above the class)
/*
Receives message from sender socket and pass them to the recipient socket
*/
public class ServerThread extends Thread
{
Socket sender;
Socket recipient;
public ServerThread(Socket sender, Socket recipient)
{
this.sender = sender;
this.recipient = recipient;
}
#Override
public void run()
{
try {
handle();
} catch (IOException e) {
e.printStackTrace();
}
}
public void handle() throws IOException
{
String msg;
// Create output stream for the recipient
OutputStream outputStream = recipient.getOutputStream();
ObjectOutputStream objOutputStream = new ObjectOutputStream(outputStream);
// Create input stream for the recipient
InputStream inputStream = sender.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
while(true) //sender.isConnected())
{
msg = objectInputStream.readUTF();
if(true) //recipient.isConnected())
objOutputStream.writeUTF(msg);
else
break;
}
sender.close();
recipient.close();
}
}
(Please note that i removed the condotion in the "while" and "if" since i wanted to eliminate anything that will might appear because of it)
Clients main:
public class ClientMain
{
public static void main(String[] args)
{
String s;
Scanner scan = new Scanner(System.in);
try {
ClientChat chat = new ClientChat("localhost", 7777);
//while true gets messages if any and print them to the console
chat.getMessages();
s = scan.nextLine();
while(!s.equals("1"))
{
chat.sendMessage(s);
s = scan.nextLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Clients Thread:
public class ClientChat
{
Socket socket;
String ip;
int port;
OutputStream outputStream;
ObjectOutputStream objOutputStream;
InputStream inputStream;
ObjectInputStream objectInputStream;
public ClientChat(String ip, int port) throws UnknownHostException, IOException
{
this.ip = ip;
this.port = port;
socket = new Socket(ip, port);
// Create output stream for the recipient
outputStream = socket.getOutputStream();
objOutputStream = new ObjectOutputStream(outputStream);
// Create input stream for the recipient
inputStream = socket.getInputStream();
objectInputStream = new ObjectInputStream(inputStream);
}
public void getMessages() throws IOException
{
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(true)//socket.isConnected())
{
String msg;
try {
msg = objectInputStream.readUTF();
System.out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
public void sendMessage(String message)
{
try {
objOutputStream.writeUTF(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Well, this code doesn't work,
I have run the server and two clients, the clients do connect to the server, and you can
enter input to readLine() method, but nothing happen.
i have tried to dubug the server, what i found is that it stack on the line:
msg = objectInputStream.readUTF();
that all the relevant info i have, if you need some more information please comment
You need to call the flush() method from the ObjectOutputStream object. If you don't the data to send are stored in an internal buffer. It will get only send when the buffer is full or when you explicit call the flush() method.

Simple chat client and chat server [duplicate]

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.

Java "NotSerializableException: java.net.Socket" When Not Sending A Socket

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.

Java socket works only for one client, blocked after server accept

I have a problem with my client/server program, which is blocked after one client is connected. My one client can communicate with my server, but when I try to connect another, the second can't connect. I never see my 'ok' on my console:
public class Server{
private Map<Integer,ThreadClient > mapThreads;
private ServerSocket serveur ;
public static void main(String args[])
{
try{
Serveur serv = new Server();
serv.setServer( new ServerSocket(4786,2));
while (true)
{
serv.getMapThreads().put(new ThreadClient(serv.getServer().accept(),serv);
System.out.println("ok");
}
}
catch (Exception e) { }
}
class ThreadClient implements Runnable
{
private Thread t;
private Socket socket;
private ObjectOutputStream oos ;
private ObjectInputStream ois;
private Serveur server;
public ThreadClient(Socket s, Server serv ) throws ClassNotFoundException
{
server = serv;
socket=s;
try{
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
}
catch (IOException e){ }
t = new Thread(this);
t.start();
}
public void run()
{
try
{
while(true){
// send and recev message
}
}
}
catch (Exception e){ }
}
Move the construction of the object streams out of the constructor and into the run() method. The process implies I/O with the peer so it shouldn't be carried out in the accept() thread.

Java Sockets: Connection but no Stream?

I'm trying to write a little SocketServer and a fitting ClientApplet. The connection works (I echo out incoming/closing connections), but the server does not get any InputStream.
I just can't fix the problem and feel a bit lost :/
The complete project is here.
Here is the responsible part of my server:
MessageService.java
public class MessageService implements Runnable {
private final Socket client;
private final ServerSocket serverSocket;
MessageService(ServerSocket serverSocket, Socket client) {
this.client = client;
this.serverSocket = serverSocket;
}
#Override
public void run() {
PrintWriter out = null;
BufferedReader in = null;
String clientName = client.getInetAddress().toString();
try {
out = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line;
System.out.println("Waiting for "+clientName);
/* HERE I TRY TO GET THE STREAM */
while((line = in.readLine()) != null) {
System.out.println(clientName + ": " + line);
out.println(line);
out.flush();
}
}
catch (IOException e) {
System.out.println("Server/MessageService: IOException");
}
finally {
if(!client.isClosed()) {
System.out.println("Server: Client disconnected");
try {
client.close();
}
catch (IOException e) {}
}
}
}
}
Part of Client
QueueOut.java
public class QueueOut extends Thread {
Socket socket;
public ConcurrentLinkedQueue<String> queue;
PrintWriter out;
public QueueOut(Socket socket) {
super();
this.socket = socket;
this.queue = new ConcurrentLinkedQueue<String>();
System.out.print("OutputQueue started");
}
#Override
public void start() {
try {
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
System.out.println("Running outputqueue");
while(true) {
if(this.queue.size() > 0) {
String message = this.queue.poll();
System.out.println("Sending "+message);
out.println(message+"\n");
}
}
}
catch (IOException ex) {
System.out.println("Outputqueue: IOException");
}
}
public synchronized void add(String msg) {
this.queue.add(msg);
}
}
I have reduced my post to the (as i think) necessary parts :)
Try getting your input stream before you get the output stream, even though you're not using it, you should match the inverse order on your client and your server (as discussed in another similar threads).
Edit:
Also see Socket programming
Good Luck!

Categories

Resources