why it didn't go through the thread? - java

I was checking if the sign Up button is clicked it do something in another thread but it didn't go to the end of thread ?
if(!(email.isEmpty() ||username.isEmpty() || password.isEmpty())){
Main.users.add(new User(username, password, email));
new Thread(new SocketSender(Main.socket, Main.users)).start();
Thread.sleep(1000);
System.out.println("here");
new Thread(new ServerReciver(Main.socket)).start();
Thread.sleep(2000);
System.out.println("here");
Main.pstage.setScene(new Scene(FXMLLoader.load(getClass().getResource("/sample/logIn.fxml")),700,700))}
Socket Sender
public class SocketSender implements Runnable{
Socket socket;
Object object;
public SocketSender(Socket socket, Object object) {
this.socket = socket;
this.object = object;
}
#Override
public void run() {
try {
ObjectOutputStream write = new ObjectOutputStream(socket.getOutputStream());
write.writeObject(object);
write.flush();
} catch (IOException e) {
e.printStackTrace();
}
}}
Server Reciver
public class ServerReciver implements Runnable {
Socket socket;
public ServerReciver(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
System.out.println("log1");
try {
System.out.println("log2");
ObjectInputStream read = new ObjectInputStream(socket.getInputStream());
System.out.println("log3");
Object o = read.readObject();
System.out.println("ma");
if(o instanceof User){
System.out.println(log4);
Server.getUsers().add((User) o);
}
else if(o instanceof Artist){
Server.getArtists().add((Artist) o);
}
else if(o instanceof PlayList){
Server.getPlayLists().add((PlayList) o);
}
else if(o instanceof Song){
Server.getSongs().add((Song) o);
}
else if(o instanceof Album){
Server.getAlbums().add((Album) o);
}
System.out.println(log6);
Server.write();
System.out.println(log7);
Thread.sleep(100);
System.out.println(Server.getUsers().get(0));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
in the Server receiver it prints the 2 first log but it didn't print all the logs!?

Your problem is simply: you can't use the same socket object to send and read data at the same time.
What you are trying is like: using your own mobile phone to call your own number and then talk to you (in a way that works).
In other words: instead of reusing some Main.socket you simply have to create two distinct sockets in the first place.
But of course, there is zero point in doing things in this order. Don't build a JavaFX application and then try to add in client/server connectivity to a remote system.
Start by learning how to do that client/server thing, for example by reading the corresponding Oracle tutorial. And then, when you have written small command line tools that nicely communicate via sockets; even to a remote system; then take that knowledge forward and build it into your JavaFX application. Instead of trying to learn juggling while learning to use the unicycle.

To create server's client use java.net.Socket:
Socket s = new Socket(serverAddress, 9090);
BufferedReader input =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
To create server use java.net.ServerSocket :
ServerSocket listener = new ServerSocket(9090);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
} finally {
listener.close();
}

Related

java client server objects serialization: read objects in the same order they were sent

I'm developing a client server application in java. Communication takes place by serializing/deserializing immuable objects containing the information required, with ObjectOutputStream and ObjectInputStream.
In the server, every time I accept a new tcp connection, I instantiate a new Thread to handle the connection with that particular client.
This thread has a reference to the socket and it keeps reading objects:
while (true){
Object receivedObject = inputStream.readObject();
if (receivedObject instanceof MessageA){
//do sth
} else if (receivedObject instanceof MessageB){
//do sth else
}
this Runnable also has a method to send objects to the client:
public void sendMessage(Message message) {
try {
output.writeObject(message);
output.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
client-side, when the user enters the server's address, I instantiate a SocketClient object to handle the communication with the server:
public class SocketClient extends Observable {
private final Socket socket;
private final ObjectOutputStream outputStream;
private final ObjectInputStream inputStream;
private static int TIMEOUT = 5000;
public SocketClient(String serverAddress, int serverPort) throws IOException {
this.socket = new Socket();
this.socket.connect(new InetSocketAddress(serverAddress, serverPort), TIMEOUT);
this.outputStream = new ObjectOutputStream(socket.getOutputStream());
this.inputStream = new ObjectInputStream(socket.getInputStream());
}
public void readMessage() {
Thread readerThread = new Thread(() -> {
boolean read = true;
while (read) {
Message message;
try {
message = (Message) inputStream.readObject();
notifyObservers(message);
} catch (IOException | ClassNotFoundException e) {
message = new ErrorMessage(null, "Connection lost with the server.");
disconnect();
read = false;
}
}
});
readerThread.start();
}
public void sendMessage(Message message) {
try {
outputStream.writeObject(message);
outputStream.reset();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void disconnect() {
try {
socket.close();
} catch (IOException e) {
// disconnection error
e.printStackTrace();
}
}
}
messages are sent and received in both applications, the only problem is that when I send multiple messages sequentially in the server, they are sometimes received in a different order in the clients.
How may I fix that?

Manage all incoming chat messages in java socket programming

I am developing a program that has a chat feature and I am using sockets in it.
In my case, I want to handle each of the client in a different window chat(PLEASE SEE ATTACHED IMAGE).
As of now, when 1 client is connected, there is no problem. But when 2 clients are connected, the first client will be overridden by the 2nd one and he can't receive messages from server not unless I close the connection for the latest client connected(Server still receiving messages from all client although only 1 client can receive from server).
How am I gonna do this? I am using captain casa framework
I want to manage it like what did the image below do.
IMAGE HERE
Here is my code:
Server:
public void mainserver(){
Thread server = new Thread(new Runnable() {
#Override
public void run() {
try {
serverSocket = new ServerSocket(port);
System.out.println("Server Online... \nWaiting for Connections");
} catch (IOException e) {
e.printStackTrace();
}
while (accept){
try {
socket = serverSocket.accept();
System.out.println("New Connection Estasblished!!!");
chatHandler chat = new chatHandler(socket);
chat.start();
} catch (IOException e) {
System.out.println("server not terminate all connections");
System.exit(-1);
}
}
}
});
server.start();
}
public class chatHandler extends Thread{
Socket socket;
public chatHandler(Socket socket){
this.socket = socket;
}
public void run(){
try {
din = new DataInputStream(socket.getInputStream());
dout = new DataOutputStream(socket.getOutputStream());
dout.writeUTF("Hi! Thank you for reaching us! How may I help you!?");
while (!read.equals(".end")){
read = din.readUTF();
if (getServerArea()!=null){
setServerArea(getServerArea()+"\n"+read);
}else {
setServerArea(read);
}
}
System.out.println("end of chat server");
} catch (IOException e) {
e.printStackTrace();
}finally {
System.out.println("Exit");
try {
dout.close();
din.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void serverSend(javax.faces.event.ActionEvent event) { // "Send" button
write = getServerField();
try {
dout.writeUTF(write);
dout.flush();
if (getServerArea()!=null){
setServerArea(getServerArea()+"\n"+write);
setServerField("");
}else {
setServerArea(write);
setServerField("");
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(write);
}
Client:
public void client(){
Thread client = new Thread(new Runnable() {
#Override
public void run() {
try {
socket = new Socket("localhost",port);
din = new DataInputStream(socket.getInputStream());
dout = new DataOutputStream(socket.getOutputStream());
while (!read.equals("bye")){
read = din.readUTF();
if (getClientArea()!=null){
setClientArea(getClientArea()+"\n"+read);
}else {
setClientArea(read);
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
din.close();
dout.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
client.start();
}
public void clientSend(javax.faces.event.ActionEvent event) {
write = getClientField();
try {
dout.writeUTF(write);
dout.flush();
if (getClientArea()!=null){
setClientArea(getClientArea()+"\n"+write);
setClientField("");
}else {
setClientArea(write);
setClientField("");
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(write);
}
I believe I understand the problem, and how to correct it.
You are using a unique thread (chatHandler) for each new connection.
This thread writes an automatic "Hello" upon connection, but thereafter is dedicated to reading messages (in the while loop you only read din) and updating the console accordingly. Since each thread is managing a reference to din, all incoming messages are OK.
However, it seems that writing back to a client (serverSend) is not in a thread; it is triggered by a button event. At this point, dout will be a reference to the most recent connection, and not a reference to the client intended to get the message. That is why the most recent client gets all future messages.
The correction is to choose the correct 'dout' for the intended client. When the server 'operator' chooses to write a message back (clicking the send button), somehow you need to obtain the correct 'dout' for that client.
One way to do this is to establish dout prior to creating the thread (using socket), and maintain a relationship between each client, and it's corresponding dout (i.e. in a Map).
If the problem is still not clear (that each client must have a unique reference to dout), please let me know and I will try to clarify.

how can I have a linked list that multiple clients can read write to?

I have a multithreaded server and can have multiple clients at once connected. These threads call a class that has multiple linked lists and the clients can add and remove information to it.
For example
This is the server
public class ShareServer {
public static void main(String[] args) throws IOException {
//if (args.length != 1) {
//System.err.println("Usage: java ShareServer <port number>");
//System.exit(1);
//}
//int portNumber = 2000;
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(2000)) {
while (listening) {
new ClientThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + 2000);
System.exit(-1);
}
}
}
This is the clientsthread
public class ClientThread extends Thread {
private Socket socket = null;
private ObjectOutputStream out;
private ObjectInputStream in;
FindMatch look= new FindMatch();
string fruit;
public ClientThread(Socket socket) {
super("ClientThread");
this.socket = socket;
}
public void run() {
try {
out = new ObjectOutputStream (socket.getOutputStream());
in = new ObjectInputStream (socket.getInputStream());
int count=0;
boolean flag = false;
try{
fruit = (Double)in.readObject();
flag = look.checkForMatch(string fruit);
if(flag==true)
sendMessage("found a match")
}
catch(ClassNotFoundException classnot){
System.err.println("Data received in unknown format");
}
socket.close();
}catch (IOException e) {
e.printStackTrace();
}
}
void sendMessage(string fuit)
{
try{
out.writeObject(msg);
out.flush();
System.out.println("server>" + msg);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
public LinkedList<String> fruitEntries = new LinkedList<Integer>();
public LinkedList<?> clientID = new LinkedList <?>();
this is the code that it calls
boolean checkFormatch(string fruit){
for(int i = 0; i< fruitEntries.length();i++){
if(fruit == fruitEntries.get(i)){
tell client at clientID(i);
fruitEntries.remove(i);
clientID.remove(i);
retutn true;
}
}
}
This code is far from perfect I just threw this together. the general idea is right though. I will have maybe 6 linked lists of info in mine.
I'm not sure how to keep track of what thread a client has either so I would appreciate help with that.
Personally I would use RMI instead of sockets. RMI handles all the messy listening threading etc.
Consider using one of the java.util.concurrent classes -- ConcurrentSkipListMap
ConcurrentHashMap
Also, when you compare Strings you need fruit.compareTo(...) which is rather slow so creating a hash is probably better.

Object stream I/O issue, client object not updated

i'm working a client-server based game. The game is mainly caracterized by a Grid object which must be synchronized between clients. To do that I use the Object I/O Streams over Sockets.
However i encounter an issue during the synchronization process. The Grid is sent and recieved by all clients but its state is not modified after the first upload to each client.
I mean by that that clients do recieve the object in its present state when they connect but subsequent receiptions (initiated by either another client connection or previous client moves) don't present any modification over the initial sent state...
here are (stripped-down) snippets of the server side code:
while(true) //continuously accept new connections
{
//wait incoming connection, and accept it
Socket newSocket = serverListener.accept();
//create player details and save it in hashtable
Player newPlayer = new Player(newSocket); //streams saved here
Players.put(newPlayer);
//update all clients
sendGridToAll();
}
The Player class constructor:
public Player(Socket s) throws IOException
{
this.Tx = new ObjectOutputStream(socket.getOutputStream());
this.Rx = new DataInputStream(socket.getInputStream());
}
The SendToAll method:
public void sendGridToAll()
{
synchronized(Players) //do nothing while players HT is being modified
{
for(Enumeration e = Players.elements(); e.hasMoreElements(); )
{
Player tmpPlayer = (Player)e.nextElement();
ObjectOutputStream tmpTx = tmpPlayer.getTx();
try {
tmpTx.writeObject(grid);
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
print.log("Grid update sent");
}
}
and here is the client side snippet handling the object reception (ran in a thread):
public void run()
{
ObjectInputStream RX = new ObjectInputStream(socket.getInputStream());
while(true)
{
try
{
RX_grid = (Grid)RX.readObject();
}
catch (IOException ex)
{
print.log("IO Error");
ex.printStackTrace();
}
catch (ClassNotFoundException ex)
{
print.log("Bad grid class UID");
}
finally
{
print.log("grid recieved");
c.updateGui(RX_grid);
}
}
}
Thank you for your help

ServerSocket java-server reads input only once?

I have written a java server and here is the code:
try
{
ss = new ServerSocket(8080);
while (true)
{
socket = ss.accept();
System.out.println("Acess given");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//out = new PrintWriter(socket.getOutputStream(),true);
line = in.readLine();
System.out.println("you input is :" + in.readLine());
}
}
And an iphone application is the client and there is the code for it:
- (void)viewDidLoad {
[super viewDidLoad];
socket = [[LXSocket alloc]init];
if ([socket connect:#"10.211.55.2" port:8080]) {
NSLog(#"socket has been created");
}
else {
NSLog(#"socket couldn't be created created");
}
#try {
}#catch (NSException * e) {
NSLog(#"Unable to send data");
}
[super viewDidLoad];
}
-(IBAction)sendData{
[socket sendString:#"A\n"];
}
I am having 2 problems here: first is that the server is only reading the input once. The second is that when ever I try to output the data it doesn't output until I have called the method twice (clicked on the uibutton twice). Not sure what is happening here. What am I doing wrong?
You are creating a new reader everytime in your while loop. Instead move the code outside the while loop and block on the readLine() call.
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream());
String line = "";
while ( true) {
line = in.readLine();
System.out.println("you input is :" + line);
if ( "Bye".equals(line) )
break;
}
Here is an example server side program.
Since alphazero posted the pattern, I will post a brief stripped down implementation:
This is the Server:
try {
ServerSocket ss = new ServerSocket(portNumber);
logger.info("Server successfully started on port " + portNumber);
// infinite loop that waits for connections
while (true) {
SocketThread rst = new SocketThread(ss.accept());
rst.start();
}
} catch (IOException e) {
logger.info("Error: unable to bind to port " + portNumber);
System.exit(-1);
}
The SocketThread is something like:
public class SocketThread extends Thread {
private Socket communicationSocket = null;
public SocketThread(Socket clientSocket) {
communicationSocket = clientSocket;
try {
input = new ObjectInputStream(communicationSocket.getInputStream());
} catch (IOException e) {
logger.info("Error getting communication streams to transfer data.");
try {
communicationSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void run() {
boolean listening=true;
DataObject command = null;
while (listening) {
try {
Object currentObject = input.readObject();
if (currentObject != null
&& currentObject instanceof DataObject) {
command = (DataObject) currentObject;
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// If we got to this point is because we received a request from
// the client
// we can exit the loop
listening = false;
}
}
}
}
Note: "DataObject" is just a custom class which could be more practical since you can read the Dataobject itself from the socket without worrying about how many bytes you are reading, etc. Only condition is that DataObject is flagged as Serializable.
Hope it helps.
Tushar,
The general pattern is this (almost java but pseudo-code):
while (server-socket is accepting new connections)
{
// The server-socket's job is to listen for connection requests
// It does this typically in a loop (until you issue server-shutdown)
// on accept the server-socket returns a Socket to the newly connected client
//
socket s = server-socket.accept-connection();
// various options here:
//
// typically fire off a dedicated thread to servie this client
// but also review NIO or (home-grown) connection-map/handler patterns
// the general pattern:
// create a dedicated thread per connection accepted.
// pass Socket (s) to the handler method (a Runnable) and start it off
// and that is it.
// Here we use the general pattern and create a dedicated
// handler thread and pass of the new connections' socket reference
//
Thread handler-thread = new Thread (handler-routine-as-runnable, s);
handler-thread.start();
}

Categories