Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

[java] Problem with Java networking

Started by xissburg 12 replies 2.9k views
Original Post
xissburg
xissburg
Hello...I've chosen java to start learning things about networking then I picked the Java tutorial about networking and read that and started a kind of simple chatting application. But I have problems I couldn't solve in anyway... After lots of tests I've found that the problem is that the client can send messages to the server and the server perfectly receives it but if the server sends something to the client, the client doesn't receive anything. I have no idea why. The sample application in the Java tutorial works Ok here, and my app is very based on that and AFAICS everything is ok, it is much like that. Here is the source, hope it is not much for you =): Client

package chatclient;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.*;


public class MainFrame extends javax.swing.JFrame {

    public String name;
    public Socket socket;
    public BufferedReader in;
    public PrintWriter out;
    
    public MainFrame() {
        //show nickname dialog
        name = JOptionPane.showInputDialog(null, "Name", "Enter your name", JOptionPane.PLAIN_MESSAGE);
        
        //connect to server
        try {
            socket = new Socket("wha.tis.my.ip?", 4444);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "Error connecting to server. Got Exception: " 
                                        + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
            System.exit(1);
        }
        
        //open IO streams
        try {
            
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "Error opening IO streams. Got Exception: " 
                                        + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        }
        
        //send client name
        out.println(name);
        
        //should I comment about the following command? ROFL
        initComponents();
        
        //create the SwingWorker thread to manage incoming messages without fucking up the GUI
        new SwingWorker<Void, Void>()
        {
            protected Void doInBackground() 
            {
                String s = null;
                
                while(true)
                {
                    try {
                        if ((s = in.readLine()) != null) 
                            msgTextArea.append(s);
                        
                    } catch (Exception ex) {
                        System.err.println("Error reading server messages. Got exception: " + ex.getMessage());
                        ex.printStackTrace();
                    }
                    
                    Thread.yield();
                }
            }
        }.execute();
        
        //assing a WindowListener to close all that socket stuff when the window gets closed
        addWindowListener(new WindowAdapter() 
        {
            public void windowClosing(WindowEvent e)
            {
                //here I close the socket but the in the server the socket doenst closes =o
                try{
                    out.close();
                    in.close();
                    socket.close();
                }catch(Exception ex){}
            }
        });
        
        
        //show main JFrame which runs the client messaging system
        setVisible(true);
    }
                         
    private void initComponents() {
       //...I did the GUI in NetBeans...
    }                      

//when the user clicks this button the message in the textarea is sent to server. This works, the message is actually sent...
private void sendButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
    String msg = clientMsgTextArea.getText();
    clientMsgTextArea.setText(null);
    out.println(msg);
}                                          

    
    public static void main(String[] args) 
    {
        new MainFrame();
    }
    
    
    // Variables declaration - do not modify                     
    private javax.swing.JPanel clientMsgPanel;
    private javax.swing.JScrollPane clientMsgScrollPane;
    private javax.swing.JTextArea clientMsgTextArea;
    private javax.swing.JPanel msgPanel;
    private javax.swing.JScrollPane msgScrollPane;
    private javax.swing.JTextArea msgTextArea;
    private javax.swing.JButton sendButton;
    private javax.swing.JSplitPane splitPane;
    // End of variables declaration                   

}




Server

package chatserver;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

//stores client information
class Client 
{
    public String name;
    public Socket socket;
    public PrintWriter out;
    public BufferedReader in;
}

public class Main 
{
    public static ServerSocket serverSocket;
    public static ArrayList<Client> client;
    public static final String systemName = "[__system__]";
    
    //prints the String s in the output stream of all clients
    public static void printAll(String s)
    {
        for(Client c: client)
            c.out.print(s);//this doenst works. It silently fails. The message is not received by the client
    }
    
    public static void main(String[] args) 
    {
        try {
            //create server socket to accept connections
            serverSocket = new ServerSocket(4444);
        } catch (Exception ex) {
            System.err.println("Failed to create server socket. Got exception: " + ex.getMessage());
            System.exit(1);
        }
        
        //arraylist to hold information about every connected client
        client = new ArrayList<Client>();
        
        //simple thread to accept new connections
        new Thread("ConnectionT"){
            public void run()
            {
                while(true)
                {
                    try {
                        Socket socket = serverSocket.accept();
                        System.out.println("[Server]: New connection.");
                        Client c = new Client();
                        c.socket = socket;
                        c.out = new PrintWriter(socket.getOutputStream(), true);
                        c.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        c.name = c.in.readLine();
                        client.add(c);
                        
                        printAll(systemName + ": " + c.name + " gets in.\n");
                        
                    } catch (Exception ex) {
                        System.err.println("Failed to accept new connection. Got exception: " + ex.getMessage());
                    }
                    
                    Thread.yield();
                }
                
            }
        }.start();
        
        //main loop. Receives and dispatches messages for all clients
        while(true)
        {
            String batch = new String();//the message batch
            String s;
        
            //fill in the batch
            for(Client c: client)
            {
                try {
                    if(!c.socket.isClosed())
                    {
                        if(c.in.ready())
                            if ((s = c.in.readLine()) != null) //the client messages are perfectly received here
                                batch += c.name + ": " + s + "\n";
                    }
                    else
                    {
                        c.socket.close();
                        client.remove(c);
                        printAll(systemName + ": " + c.name + "gets out.\n");
                    }
                } catch (Exception ex) {
                    c.out.println(systemName + ": your message could not be sent. Got exception: " + ex.getMessage());
                }
            }
            
            //dispatch messages if any
            if(batch.length() > 0)
                printAll(batch);
            
            Thread.yield();
        }
        
    }
}




Well, thats all. If you need more information just ask. Thanks a lot for your attention... [Edited by - xissburg on February 22, 2009 7:51:06 AM]
.
xissburg
xissburg
Of course, thats why I know that the problem is that the client doesn't receive messages from the server but the opposite occurs.
.
elFarto
elFarto
You've got a c.out.print and a in.readLine. Try changing the print to a println.

Regards
elFarto
xissburg
xissburg
Hey that thing works now =P. I dont understand why it didnt work with the print() but...freak thing. THANKS =D

But I still have problems. After calling socket.close() in the client, in the server the socket doesn't get closed.

And another one is that the readLine() method blocks. I need a method to read data which doesn't block. If there is new data to be read it reads, otherwise it skips. Are there any?!

Thanks again...
.
xissburg
xissburg
Oh I got to read without blocking using BufferedInputStream. Its working now.

But the socket closing notification doesnt go to the server yet =|.
.
firepowerjohan
firepowerjohan
I also have a question concerning networking. I am developing a game (that will in the end use a web server). Currently it uses just peer2peer. Since it has support for up to 16 players and that you may want to sent some chat messages only to allies, does 16 players mean I need to setup 15 different sockets on host machine?

That is what I am doing at this moment, but someone told me it is possible to just use one socket. How?

He must mean if I want to broadcast all info to all players right? But i do not want to sometimes so then means I need to setup more sockect?

If I send through a single socket where all of the clients are listening does it mean all of them receive it or does just one of them get "first" and pick it up and discard the message?


Some details on the connection setups:

Example: Say that host listen on port 6500 and use it only for communicating with new clients.

Client connect to 6500. Host send to client the post client is going to use (since first client in this case 6500+1=6501.
Host start listening on 6501. Client connect to port 6501. They both shut down the 6500 connection.

Host start listening on port 6500 again, until all players have joined (say in a 3 player game it woudl now wait for another player and then highligth a "start" button once that player is connecting.

In game this means if host want to send something happening in game it sends that info twice, to player at port 6501 and 6502.

So client only use one socket and send all to host. Host use one socket per player. Is this correct usage?

[Edited by - firepowerjohan on February 27, 2009 9:36:55 AM]
trellend
trellend
Quote:
Original post by firepowerjohan
I also have a question concerning networking. I am developing a game (that will in the end use a web server). Currently it uses just peer2peer. Since it has support for up to 16 players and that you may want to sent some chat messages only to allies, does 16 players mean I need to setup 15 different sockets on host machine?

[snip]

So client only use one socket and send all to host. Host use one socket per player. Is this correct usage?


Each client would have one socket, the server would have # of active players sockets + 1. (the one for listening for sockets). That's how I have always done them. You mentioned 16 - which is generally the breakdown point of normal one thread per connection programs (in my experience). This will get interesting for you, as you'll have to look into overlapped non-blocking (polling) socket programming. Done right, one thread can handle 500 sockets easily.

Good luck - as that last step is always "interesting"

elFarto
elFarto
Quote:
Original post by firepowerjohan
In game this means if host want to send something happening in game it sends that info twice, to player at port 6501 and 6502.

So client only use one socket and send all to host. Host use one socket per player. Is this correct usage?


While this will work, you can just have all your clients connected to port 6500. More formally an individual socket is defined as a tuple of (client IP address, client port, server IP address, server port).

Regards
elFarto
firepowerjohan
firepowerjohan
Quote:
Original post by elFarto
Quote:
Original post by firepowerjohan
In game this means if host want to send something happening in game it sends that info twice, to player at port 6501 and 6502.

So client only use one socket and send all to host. Host use one socket per player. Is this correct usage?


While this will work, you can just have all your clients connected to port 6500. More formally an individual socket is defined as a tuple of (client IP address, client port, server IP address, server port).

Regards
elFarto


How does it work then?
Say a client want to send something to host only and there are 16 players in game. Does it mean this traffic is done x15 or can I somehow tell it to send something just to one player?
ShawnO
ShawnO
Each client will have one socket connection to the server.
The server will have one socket connection for each client. In Java the ServerSocket.accept() method returns a Socket when a client connects. If 10 clients connect to the server, the server will have 10 socket connections.
If you want to send a message to only one client, send it using the socket connection for that client. If you want to send a message to all clients, send the message on each of socket connections.
I'd be interested to know if there is a more efficient way to broadcast a message to all clients than to loop through all of the socket connections and send the message on each socket.

Shawn

When using the Windows calculator program, always remember to clear any values from memory before exiting to prevent burn-in.
firepowerjohan
firepowerjohan
[ Please don't hijack threads; create your own thread to ask questions. --Sneftel ]

[Edited by - Sneftel on March 3, 2009 10:13:57 AM]
xissburg
xissburg
...

[Edited by - xissburg on April 8, 2009 9:28:53 AM]
.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.