This question already has an answer here:
Must server & client have reverse sequence of claiming ObjectOutputStream & ObjectInputStream?
(1 answer)
Closed 4 years ago.
I am creating a client-server as follows:
Server:
Listener thread daemon (listening always for incoming connections)
Service object that send/receive data with clients connected
Client(s):
There can be many instances of clients
However, on either sides after connection is established, it takes forever to create Constructor of type ObjectOutputStream & ObjectInputStream. Bit of googling revealed this and this. I followed steps of :
1. creating ObjectOutputStream first
2. flush it
3. creating ObjectInputStream second
But this doesn't work for me. Wonder why ??
Server:
Listener Thread/daemon:
Socket connSocket;
try {
ServiceListener.serverSocket = new ServerSocket(listenPort);
System.out.println("Listening on port: " + listenPort);
while (true) {
connSocket = serverSocket.accept();
nodeList.add(connSocket);
System.out.println("Accepted connections ( " + connSocket + "):" + getConnectedNodeCount());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Server Thread (After accepting Connection)
for (int i=0; i<listenerObj.getConnectedNodeCount(); i++) {
try {
System.out.println(listenerObj.nodeList.get(i));
serviceTx = new ObjectOutputStream(listenerObj.nodeList.get(i).getOutputStream());
serviceTx.flush();
serviceRx = new ObjectInputStream(listenerObj.nodeList.get(i).getInputStream());
String rxMsg = (String) serviceRx.readObject();
if (rxMsg.equals("HELLO")) {
System.out.println("Service received: " + rxMsg);
serviceTx.writeObject((Object) "HELLO");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Client:
try {
System.out.println("Creating Node socket...");
clientSocket = new Socket(getServerIp(), getServerPort());
nodeTx = new ObjectOutputStream(clientSocket.getOutputStream());
nodeTx.flush();
nodeRx = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("Connected to " + getServerIp() + ":" + getServerPort());
do {
String outBoundMsg = new String();
outBoundMsg = "HELLO";
System.out.println("Node sending \"" + outBoundMsg + "\" to service");
nodeTx.writeObject(outBoundMsg);
nodeTx.flush();
String rcvdMsg = (String) nodeRx.readObject();
if(rcvdMsg.equals("HELLO")) {
System.out.println("++++ client says " + rcvdMsg + " ++++");
}
} while(false);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Server Console Output:
starting Listener 11...
Service Function started !!
Listening on port: 2244
Accepted connections ( Socket[addr=/127.0.0.1,port=62994,localport=2244]):1
Client Console:
Creating Node socket...
I would change the do { } while(false) to a do { } while(true) otherwise it make no sense to have a while loop that runs only once and exit, i.e. the do-while(false) loop acts just as if it is not there.
Related
I have developed a simply video game and I want to update it with the multiplayer functionality using websockets. I want to have two versions of the game. The first one to work as server and the other version as a client. I want to initialize the game from the server and to wait for the reaction of the client. My first question: is it possible to run server and client in the same machine (give as an input the same ip)? Secondly I am using the following code in order to create the sockets from the server side:
try {
serverSocket = new ServerSocket(10007);
}
catch (IOException e)
{
System.err.println("Could not listen on port: 10007.");
System.exit(1);
}
System.out.println ("Waiting for connection.....");
try {
clientSocket = serverSocket.accept();
}
catch (IOException e)
{
System.err.println("Accept failed.");
System.exit(1);
}
System.out.println ("Connection successful");
When I am trying to connect from the client it seems that the whole thing its not working as i am receiving the message waiting for connection.... My code for connecting the client is the following:
String serverHostname = new String("ip");
if (args.length > 0)
serverHostname = args[0];
System.out.println("Attemping to connect to host " +
serverHostname + " on port 10007.");
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
echoSocket = new Socket(serverHostname, 10007);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: " + serverHostname);
System.exit(1);
}
What can it be the issue here?
Your Server Side Code is fine. just a little note here, the ServerSocket.accept(); method is ablocking call, meaning that program execution will halt there until a client connects to it.
Secondly i can see an issue from the first line of your client code below
if (args.length > 0)
serverHostname = args[0];
args[0] may not be an ip address, i'm not too sure about how java command line applications behave but in c++ for instance, args[0] in the right context is always the absolute path of the program executable. this may be the case in java too.
So you may be passing an ip address but will actually be passed in as args[1].
I am attempting a client/server type chat box (using GUI's). I won't get into details of the multi-threading I used in the program since I believe it is not part of the problem (I hope not) and it will be good amount of code to post. Anyways, for both my client and my server I create a socket, and some other stream classes within a try block, and some reason the sockets close after the catch blocks. PS I do NOT call socket.close() method anywhere that could end if early
Server, this is ran into a constructor of one of my class. It breaks down into, my main has the actually server stuff on a different thread, (like my previous post) it is a fix so that the gui can load and run the server stuff without one waiting on the other. Anyways, without all that detail, here is my code
public ChatAppProtocol(Socket sock)
{
super("ChatAppServer");
// this also has a clas var of Socket
this.sock = sock;
try (
PrintWriter output = new PrintWriter(this.sock.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(this.sock.getInputStream())) ;
)
{
// first stream of a string is the username loging in from client
String name = input.readLine();
// this returns false, so its not closed
System.out.println("closed?: " + this.sock.isClosed());
}
catch (IOException e)
{
e.printStackTrace();
}
// PROBLEM!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// closed after the catch blocks before methods even ends
// p.s. i also plan on using the socket in another method but can't since it closes
System.out.println("closed?: " +this.sock.isClosed());
}
now my client
#FXML
private void login()
{
this.name = this.username.getText().trim();
this.portnum = Integer.parseInt(this.port.getText());
this.name = this.username.getText().trim();
this.ipaddr = this.ip.getText().trim();
try (t
Socket socket = new Socket(this.ipaddr, this.portnum);
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
)
{
this.sock = socket;
output.println(this.name);
// this returns false, not closed
System.out.println("closed?: " +this.sock.isClosed());
}
catch (UnknownHostException e)
{
System.err.println("Problem at ip: " + this.ipaddr);
System.exit(1);
}
// PROBLEM!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// returns true here, closes before methods end and i cant reuse it
System.out.println("IS IT CLOSED!!!!!! " + this.sock.isClosed());
}
}
so, any reason why both this different class, different files, different project sockets close after try-catch blocks? Can't find answer online, and been on it for a while and I am stuck. I found out about this problem after seeing this on the server side console
java.net.SocketException: Socket is closed
at java.net.Socket.getOutputStream(Socket.java:943)
at chatappserver.ChatAppProtocol.run(ChatAppProtocol.java:62)
Because you're creating socket with the brackets of the try block, it is automatically closed upon exiting the block. Instead, try creating it inside the block itself and it shouldn't be closed:
try {
this.sock = new Socket(this.ipaddr, this.portnum);
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
output.println(this.name);
} catch (UnknownHostException e) {
System.err.println("Problem at ip: " + this.ipaddr);
System.exit(1);
}
// this.sock should still be open at this point.
Have a read of the Java tutorial on try-with-resources for more information on why you're getting your current behaviour.
You are using try-with-resources, which is roughly an equivalent of:
try
{
this.sock = new Socket(this.ipaddr, this.portnum));
output.println(this.name);
// this returns false, not closed
System.out.println("closed?: " +this.sock.isClosed());
}
catch (UnknownHostException e)
{
System.err.println("Problem at ip: " + this.ipaddr);
System.exit(1);
} finally {
if (this.sock != null)
this.sock.close();
}
Just initialize the socket outside the resources clause of try (...) and it won't get closed
I'm working on a java server-client based file transfer over socket project, I'll sum up the project shortly, I have text files related to server and client, server related text contains which ports are going to be opened and client text contains the IP and port to be connected on(server side is like 4444 and client side is like 4444 localhost) The file transfer on a single client is running pretty ok, now I'm working on second client connection and transfer, what I'm trying to do is; when a second client is run, it will read the first line of the text file (which is already in use by the first client), I thought a recursion will solve the problem but seems I couldn't figure out what I've done wrong, below are the code snippet from client side
boolean connected = false;
private void connection() {
while (!connected) {
try {
FileReader fr = new FileReader("c_input.txt");
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
String delims = "[ ]";
String[] elements = new String[8];
elements = line.split(delims);
serverPort = Integer.parseInt(elements[portIndex]);
hostIP = elements[ipIndex];
clientSocket = new Socket(hostIP, serverPort);
is = clientSocket.getInputStream();
if (is != null) {
connected = true;
System.out.println("connected to " + hostIP + " from port "
+ serverPort);
br.close();
fr.close();
} else {
System.out.println("The port " + serverPort
+ " is occupied, now trying another port.");
portIndex = portIndex + 2;
ipIndex = ipIndex + 2;
connection();
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
}
I used recursion there, because if a port is bound by another client it has to read another line from text file and split and retry connection with the new line's inputs.(in terms short the whole method will run again) But when it comes to running, the first client connects and when second one tries to connect from same port with client1 the code still gets in if loop instead of getting in else block (I get the message from the if check's println on the console and by the way is in the if check stands for InputStream) which means there is a stream coming from server, is this normal? if so how can I achieve the whole thing connection method does all over again if the port is bound by another client?
I wrote a simple program where a server should print data sent by multiple clients. But the server receives only partial data. Following are the relevant pieces of the code.
Server:
try {
serverSocket = new ServerSocket(8888);
} catch (IOException e) {
System.err.println("Could not listen on port: 8888");
System.exit(-1);
}
while (listening) {
Socket clientSocket = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
System.out.println(reader.readLine());
reader.close();
clientSocket.close();
}
serverSocket.close();
Client:
try {
socket = new Socket("nimbus", 8888);
writer = new PrintWriter(socket.getOutputStream(), true);
localHost = InetAddress.getLocalHost();
}
catch (UnknownHostException e) {}
catch (IOException e) {}
StringBuilder msg1 = new StringBuilder("A: ");
for(int i=1; i<=3; i++)
msg1.append(i).append(' ');
writer.println(localHost.getHostName() + " - " + msg1);
StringBuilder msg2 = new StringBuilder("B: ");
for(int i=4; i<=6; i++)
msg2.append(i).append(' ');
writer.println(localHost.getHostName() + " - " + msg2);
StringBuilder msg3 = new StringBuilder("C: ");
for(int i=7; i<=9; i++)
msg3.append(i).append(' ');
writer.println(localHost.getHostName() + " - " + msg3);
writer.close();
socket.close();
I get the following output (when run on 3 clients)
nimbus2 - A: 1 2 3
nimbus3 - A: 1 2 3
nimbus4 - A: 1 2 3
I don't get the second and third messages. Server keeps waiting. Where am I going wrong?
Edit: In the server code, I tried removing reader.close() and clientSocket.close(). That didn't work either. Another question -- if 3 clients send 3 messages, does it require 9 connections? (this is the reason, I closed the connection in the server code)
You probably want to be delegating the handing of the socket to another thread. I've written up an example that works by passing each incoming socket to an Executor so it can read all the inputs. I use a Executors.newCachedThreadPool() which should grow to be as big as needed. You could also use Executors.newFixedThreadPool(1) if you want it to only be able to handle 1 client at a time.
The only other change I made was I removed the BufferedReader and replaced it with a Scanner. I was having issues with the BufferedReader not returning data. I'm not sure why.
Executor exe = Executors.newCachedThreadPool();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8888);
} catch (IOException e) {
System.err.println("Could not listen on port: 8888");
System.exit(-1);
}
while (listening) {
final Socket clientSocket = serverSocket.accept();
exe.execute(new Runnable() {
#Override
public void run() {
try {
Scanner reader = new Scanner(clientSocket.getInputStream());
while(reader.hasNextLine()){
String line = reader.nextLine();
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
serverSocket.close();
It looks like you close the connection to the client before they can finish writing/before the server reads all of the messages they sent. I think you need to continue to readline, and potentially not terminate the client's connection after they send you one message.
John is right.
you close the client connection by calling clientsocket.close() after reading the message that is why you cannot get the other messages. you should call clientsocket.close() when you have received all the messages
I want to run OSGi framework on another computer (in a main method). So I wanted to know is there any way to connect to the OSGi console from the other computer and manage bundles?
I thought maybe using a java.net.Socket would help, and that's how I implemented that. I've used 2 threads. one for processing user input stream, and the other one that processes OSGi Console response. This is the first thread (processes user input stream):
configMap.put("osgi.console", "6666");
Framework fwk = ff.newFramework(configMap);
try {
fwk.start();
} catch (BundleException e) {
e.printStackTrace();
}
//__________________________________________________________________//
try {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
Socket socket = new Socket(InetAddress.getByName("0.0.0.0"), 6666);
printlnInfo("Socket has been created: " + socket.getInetAddress() + ":" + socket.getPort());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
ConsoleOutputReciever fr = new ConsoleOutputReciever();
new Thread(fr).start();
while (true) {
String userInput = "";
while ((userInput = stdIn.readLine()) != null) {
System.out.println("--> " + userInput);
out.write(userInput + "\n");
out.flush();
}
System.out.println("2");
}
} catch (Exception e1) {
e1.printStackTrace();
}
This is the second thread (processes OSGi Console response):
public class ConsoleOutputReciever implements Runnable {
public Scanner in = null;
#Override
public void run() {
printlnInfo("ConsoleOutputReciever Started");
try {
Socket socket = new Socket(InetAddress.getByName("0.0.0.0"), 6666);
printlnInfo("Socket has been created: " + socket.getInetAddress() + ":" + socket.getPort());
String osgiResponse = "";
in = new Scanner(socket.getInputStream());
try {
while (true) {
in = new Scanner(socket.getInputStream());
while (in.hasNext()) {
System.out.println("-- READ LOOP");
osgiResponse = in.nextLine();
System.out.println("-- " + osgiResponse);
}
}
} catch (IllegalBlockingModeException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
but I only receive the first response of the OSGi console. like this:
--READ LOOP
--
--READ LOOP
ss
--> ss
Any ideas about the problem or any other way to connect to OSGi console remotely?
you are using blocking io, thus your inner while loop will never finish until the socket is closed. you need 2 threads to accomplish this with blocking io streams. 1 thread reads from stdin and writes to the socket output stream, the other thread reads from the socket input stream and writes to stdout.
also, you probably want to write a newline after sending the userInput to the osgi console (Scanner.nextLine() eats the newline).
lastly, you don't generally want to use the Print* classes when working with sockets as they hide IOExceptions.
Instead of building your own thing you might want to use one of the remote shells that are available, for example the Apache Felix one at http://felix.apache.org/site/apache-felix-remote-shell.html