Instance variable scope in java - java

Hello good day to all.
I am creating a networking program in java for my Internet Cafe. I have this code for my server
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
public class Server
{
private String name;
private int id;
private Socket socket = null;
private ServerSocket serversocket = null;
private ObjectInputStream ois = null;
public Server()
{
new Thread(receive).start();
while(true)
{
try
{
serversocket = new ServerSocket(4445);
socket = serversocket.accept();
System.out.println("Connected..");
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Runnable send = new Runnable(){
public void run ()
{
}
};
Runnable receive = new Runnable(){
public void run ()
{
while(true)
{
try
{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
User user = (User) ois.readObject();
System.out.println(user);
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
};
public static void main(String [] args)
{
new Server();
}
}
My problem is that I cant access my instance variable inside my Runnable interface code.
For example the "socket" instance. is not accessible inside this code
Runnable receive = new Runnable(){
public void run ()
{
while(true)
{
try
{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
User user = (User) ois.readObject();
System.out.println(user);
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
};
What is the best approach on this and why is not accessible inside that code?

Why? Here is the answer: Why are only final variables accessible in anonymous class?
If you need access to your socket from your server you should declare as a final varible your Socket socket on your Server class.

Try this
public Server() {
try {
serversocket = new ServerSocket(4445);
while (true) {
socket = serversocket.accept();
new Thread(receive).start();
System.out.println("Connected..");
}
} catch (IOException e) {
e.printStackTrace();
}
}

If I recall correctly, you need to make the socket field final. The reason escapes me right now.

Related

ObjectInputStream DeadLock

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.

java.net.SocketException: Socket is closed between Socket.accept() and Socket.getInputStream()

I'm trying to create a client/server connection and am still quite new to java as well. So the error I am getting tells me that the socket is closed. Following some work, I've managed to write the given code below. I do believe there is something wrong with the way I pass the socket to the connection class, if I had to guess, that causes the socket object to possibly be closed?
I've tried adding waits just in case the server thread hadn't been executed but that didn't seem to affect anything. Maybe I should launch the server with its own launcher in its own command prompt, but I thouht this should work just fine to test the client and server.
I can't seem to find out why my socket is closed before I send my message. Any insights would be greatly appreciated!
Thanks!
Error
java.net.SocketException: Socket is closed
at java.net.Socket.getInputSTream(Unknown Source)
at Connection.run(Connection.java:17)
Server.java
//main calling snippet.
import java.lang.Thread;
public class Server {
public static void main(String[] args) {
if(args.length != 1) {
System.err.println("Usage: java Server <port number>");
System.exit(1);
}
int port = Integer.parseInt(args[0]);
Thread server = new KServer(port);
server.start();
//added waits just to make sure the thread was executed?
//thinking this might be my problem
long t = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < t) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
KClient client = new KClient("127.0.0.1",port);
while (!(client.openConn())) {
System.out.println("Failed to connect. Retrying...");
}
client.send("Hello World");
client.closeConn();
}
}
KServer.java
//the actual server class that manages listening and threading the sockets
import java.net.*;
import java.io.*;
public class KServer extends Thread {
private int port;
private ServerSocket sSock;
public KServer(int thisPort) {
port = thisPort;
try {
sSock = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
try (Socket cSock = sSock.accept();) {
Thread con = new Connection(cSock);
con.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Connection.java
//Manages sending and receiving messages
import java.net.Socket;
import java.io.*;
public class Connection extends Thread {
Socket socket;
public Connection(Socket s) {
socket = s;
}
public void run() {
String msg;
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((msg = in.readLine()) != null) {
System.out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
KClient.java
//manages the clients connection life to the server
import java.net.*;
import java.io.*;
public class KClient {
private Socket sock;
private String dest;
private int port;
private OutputStreamWriter out;
public KClient(String dst,int prt) {
dest = dst;
port = prt;
}
public boolean openConn() {
try {
sock = new Socket(dest,port);
out = new OutputStreamWriter(sock.getOutputStream(),"ISO-8859-1");
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public void send(String msg) {
try {
out.write(msg);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void closeConn() {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Don't use try-with-resources to accept the socket. It wil close the accepted socket, which needs to stay open so the handling thread can use it. The handling thread is responsible for closing it.

How to stop all instances of a thread

I'm developping a socket-based game in Java about riddles in a competitive way.
The server program creates a response thread besides other threads for each player (client), what I want to do is stop (or interrupt) all those response threads once a player sends the right response.
Here's my code
public class testReponse implements Runnable {
private Socket socket;
BufferedReader in;
PrintWriter out;
String reponse="";
public testReponse(Socket socket2){
socket = socket2;
}
#Override
public void run() {
while(!reponse.equals("right")){
try {
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream());
String reponse = in.readLine();
System.out.println("Reponse : "+ reponse);
if(reponse.equals("right")){
out.println("correct");
out.flush();
} else {
out.println("incorrect");
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
It is not clear where is your server code is. However, the way I would do it is by having an AtomicBoolean as an instance variable in the server code. Once the "right" message is received from any of the clients, the value would change to false. In the code in the server side if you see that the value is false, then you stop!
This is one way to go about it but there might be better ways to do it though.
public class MyServer {
private AtomicBoolean keepServerOn = new AtomicBoolean(true);
public void setKeepServerOff() {
keepServerOn.set(false);
}
public void shouldKeepGoing() {
return keepServerOn.get();
}
public static void main(Strings[] args) {
....// where you accept clients and create TestResponse
MyServer myServer = new MyServer();
...// somewhere new TestResponse(socket, myServer);
}
}
public class testReponse implements Runnable {
private MyServer server;
private Socket socket;
private AtomicBoolean keepServerOn = new AtomicBoolean(true);
public testReponse(Socket socket2, MyServer server){
socket = socket2;
}
#Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream());
while(server.shouldKeepGoing()){
String reponse = in.readLine();
System.out.println("Reponse : "+ reponse);
if(reponse.equals("right")){
server.setKeepServerOff();
out.println("correct");
out.flush();
} else {
out.println("incorrect");
out.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out!= null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Socket Issue - Only first message read

I am very new to sockets and was hoping someone could help me. I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works. The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept(); even though im pretty sure the sender is still sending messages
Can anyone see what i might be doing wrong here please?
Thanks
public class Sender {
Socket server = null;
DataInputStream inp = null;
PrintStream outp = null;
public Sender(){
server = new Socket("127.0.0.1" , 3456);
outp = new PrintStream(server.getOutputStream());
}
private void connectAndSendToServer(String message) {
outp = new PrintStream(server.getOutputStream());
outp.print(message + "\n");
outp.flush();
}
}
Receiver class
public class Receive{
public String receiveMessage(int port) {
String message= null;
ServerSocket listener = null;
Socket client = null;
try{
listener = new ServerSocket(port);
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
return br.readLine();
}
...
finally{
try {
if(client!=null && listener!=null){
client.close();
listener.close();
}
}
catch (IOException e) {
}
}
return message;
}
}
This because a ServerSocket is used as an entry point for a normal Socket. accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket. It sits there and waits for a new connection to spawn a new Socket which is then used for data.
This means that while receiving messages you should call just readLine() to read from the specific Socket. Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.
Socket socket = serverSocket.accept();
ClientThread thread = new ClientThread(socket);
class ClientThread extends Thread {
Socket socket;
public void run() {
while (!closed) {
String line = reader.readLine();
...
}
}
You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.
You are not using ServerSocket correctly. You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection. Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.
Something like (< condition met > is pseudo-code defines your condition to accept new connections):
while(< condition met >) {
try {
client = listener.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = br.readLine();
//do something with str
} finally {
//close client socket
}
}
Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.
Try this basic Chatting Server written by me. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
// ///----------------------------------------Instance Variable Fields
ServerSocket ss = null;
Socket incoming = null;
// ///----------------------------------------Instance Variable Fields
// ///---------------------------------------- static Variable Fields
public static ArrayList<Socket> socList = new ArrayList<Socket>();
// ///---------------------------------------- static Variable Fields
public void go() {
try {
ss = new ServerSocket(25005);
while (true) {
incoming = ss.accept();
socList.add(incoming);
System.out.println("Incoming: " + incoming);
new Thread(new ClientHandleKaro(incoming)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandleKaro implements Runnable {
InputStream is = null;
OutputStream os = null;
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
boolean isDone = false;
Socket sInThread = null;
public ClientHandleKaro(Socket sxxx) {
this.sInThread = sxxx;
}
#Override
public void run() {
if (sInThread.isConnected()) {
System.out.println("Welcamu Clienta");
System.out.println(socList);
}
try {
is = sInThread.getInputStream();
System.out.println("IS: " + is);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = sInThread.getOutputStream();
pw = new PrintWriter(os, true);
String s = new String();
while ((!isDone) && (s = br.readLine()) != null) {
String[] asx = s.split("-");
System.out.println("On Console: " + s);
// pw.println(s);
Thread tx = new Thread(new ReplyKaroToClient(s,
this.sInThread));
tx.start();
if (asx[1].trim().equalsIgnoreCase("BYE")) {
System.out.println("I am inside Bye");
isDone = true;
}
}
} catch (IOException e) {
System.out.println("Thanks for Chatting.....");
} finally {
try {
Thread tiku = new Thread(new ByeByeKarDo(sInThread));
tiku.start();
try {
tiku.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Accha to hum Chalte hain !!!");
System.out.println(socList);
br.close();
pw.close();
sInThread.close();
} catch (IOException e) {
}
}
}
}
class ReplyKaroToClient implements Runnable {
public String mString;
public Socket mSocket;
public ReplyKaroToClient(String s, Socket sIn) {
this.mString = s;
this.mSocket = sIn;
}
#Override
public void run() {
for (Socket sRaW : socList) {
if (mSocket.equals(sRaW)) {
System.out.println("Mai same hun");
continue;
} else {
try {
new PrintWriter(sRaW.getOutputStream(), true)
.println(mString);
} catch (IOException e) {
System.out.println("Its in Catch");
}
}
}
}
}
class ByeByeKarDo implements Runnable {
Socket inCom;
public ByeByeKarDo(Socket si) {
this.inCom = si;
}
#Override
public void run() {
try {
new PrintWriter(inCom.getOutputStream(), true)
.println("You have Logged Out of Server... Thanks for your Visit");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().go();
}
}

Java - Listening to a socket with ObjectInputStream

Ok so , i have a thread class called 'Client' every time the server accepts a connection it creates a new Client....The run method listens for messages from the client and i am useing ObjectInputStream ..
do {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(socket.getInputStream());
String message = (String) in.readObject();
System.out.println(message);
}
catch (ClassNotFoundException ex) {
isConnected = false;
System.out.println("Progoramming Error");
}
catch (IOException ex) {
isConnected = false;
System.out.println("Server ShutDown");
System.exit(0);
}
} while(isConnected);
The Problem i have is that why do i have to create a new ObjectInputStream every time it loops...and if i close the input stream at the end of the loop and it loops again for another message i will get a error...Please some one help
Only create the ObjectInputStream once (outside the loop) for a client connection, then put the readObject method into the loop.
Here's a working test class:
public class TestPrg {
public static void main(String... args) throws IOException {
ServerListener server = new ServerListener();
server.start();
Socket socketToServer = new Socket("localhost", 15000);
ObjectOutputStream outStream = new ObjectOutputStream(socketToServer.getOutputStream());
for (int i=1; i<10; i++) {
try {
Thread.sleep((long) (Math.random()*3000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Sending object to server ...");
outStream.writeObject("test message #"+i);
}
System.exit(0);
}
static class ServerListener extends Thread {
private ServerSocket serverSocket;
ServerListener() throws IOException {
serverSocket = ServerSocketFactory.getDefault().createServerSocket(15000);
}
#Override
public void run() {
while (true) {
try {
final Socket socketToClient = serverSocket.accept();
ClientHandler clientHandler = new ClientHandler(socketToClient);
clientHandler.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
static class ClientHandler extends Thread{
private Socket socket;
ObjectInputStream inputStream;
ClientHandler(Socket socket) throws IOException {
this.socket = socket;
inputStream = new ObjectInputStream(socket.getInputStream());
}
#Override
public void run() {
while (true) {
try {
Object o = inputStream.readObject();
System.out.println("Read object: "+o);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
In this example Strings are sent trough the ObjectStream. If you get the ClassNotFoundException (http://download.oracle.com/javase/6/docs/api/java/io/ObjectInputStream.html#readObject()) and are using an independent client and server program than you might check if both the client and the server have the class of the object to send in their class paths.
The problem i personally had with Sockets and ObjectIOStream, is that it remembers all your object addresses, so each time you send and recive them on the client, if the address of sent object is not changed it will be copied from buffer. So
So
or create new objects each time you send them ( this is not a bad idiea, because ObjectIOStream seems to has limits on this buffer)
or use another Stream for these perpouse

Categories

Resources