Here's the problem. I'm attempting to set up a very simple app that will send messages to a Java server.
Here is my server code:
ServerSocket serverSocket = null;
Socket clientSocket =null;
try
{
serverSocket = new ServerSocket(4444);
System.out.println("Server Started...");
clientSocket = serverSocket.accept();
}catch(Exception e){};
Scanner in = new Scanner(clientSocket.getInputStream());
String inputLine;
while (true)
{
if(in.hasNext())
{
inputLine=in.nextLine();
System.out.println("Message from server: "+inputLine);
}
}
And here's the client code:
Socket client;
PrintWriter printwriter;
String serverIpAddress="192.168.173.1";
Button button;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button =(Button) findViewById(R.id.button);
text=(TextView) findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
client = new Socket(serverIpAddress,4444);
printwriter = new PrintWriter(client.getOutputStream());
printwriter.write("Start");
printwriter.flush();
//printwriter.close();
//client.close();
}
catch(UnknownHostException e)
{
}
catch(IOException e)
{
e.printStackTrace();
}
}
}).start();
}
});
}
I have one button, when I press it a message is sent to the server and it displays fine, but when I press the button the socket does not reconnect so I can't send the massage again.
To be clear I intend to eventually add more buttons to send different messages. I looked into creating a global socket but that didn't seem to go anywhere.
Any help is greatly appreciated.
This is because you are not closing the socket in the client code. You should close the streams & sockets in both server and client when the connection is over. Saying this, you should keep the connection alive and send several messages instead of closing the connection after sending one message.
I would for example rewrite the server code as (please note that this handles only one client):
ServerSocket serverSocket = null;
Socket clientSocket =null;
Scanner in = null;
try
{
serverSocket = new ServerSocket(4444);
System.out.println("Server Started...");
clientSocket = serverSocket.accept();
in = new Scanner(clientSocket.getInputStream());
String inputLine;
while (true) {
if(in.hasNext()) {
inputLine=in.nextLine();
System.out.println("Message from server: "+inputLine);
}
}
} catch(IOException e) {
e.printStackTrace();
} finally {
if(in != null) {
in.close();
}
if(clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Just a note: I would use DataInputStream & DataOutputStream... in this way, you could use in.readUTF() in the server side which will block until receiving something new through network. In this way, you will not have to do while(true) which will be way much better for the CPU.
Thank you all for your responses. I did get it working.
Multithreader, thank you, you were completely correct about where my problem lay. I did it a bit differently though.
I set up another class to set up the socket and created a method to start listening on the given port. In the main I just put that in a loop to keep closing and recreating the socket till the end condition is met.
Thanks again all.
Related
Is it possible to write a client-server code that can connect 2-different computers to play a multi-player game using sockets in java? Do these computers need to be connected by a cable? Or can I send the data through some other source? (Like internet..) Or is it enough if I know just the ip addresses of both computers and put that in in the sockets? Please tell me how I can do it.
You can connect computers that are on the same Wifi network. You will need to open a server and then open clients that connect to it.
The following code may help:
Server.java
ArrayList<Socket> clientSockets = new ArrayList<>();
try {
ServerSocket serverSocket = new ServerSocket(port); // port same as client
InetAddress inetAddress = InetAddress.getLocalHost();
System.out.println("Server opened at: "+inetAddress.getHostAddress());
while (true) // this keeps the server listening
{
final Socket socket = serverSocket.accept(); // this accepts incomming connections
clientSockets.add(socket); // adds current connection to an arraylist
System.out.println(timestamp()+"Connection from "+socket.getInetAddress());
Thread t = new Thread(new Runnable() // Thread handles messages sent by client that just connected
{
#Override
public void run() {
try
{
while (socket.isConnected())
{
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String fromClient = br.readLine();
if (fromClient != null)
{
//use message from client
}
else // connection might have been reset by client
{
socket.close();
clientSockets.remove(socket);
}
}
} catch (SocketException e)
{
System.out.println("Disconnection from "+socket.getInetAddress());
} catch (IOException e) {}
}
});
t.start();
}
} catch (Exception e) {}
Client.java - add two buttons, one for connecting and one for sending
bConnect.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
InetAddress address = InetAddress.getByName(host); // host IPaddress
socket = new Socket(address, port); // port same as server
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
final Timer time = new Timer(); // to get new server txt if it changes
TimerTask t = new TimerTask() {
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String kry = br.readLine();
// use message from server
} catch (Exception e1) {
JOptionPane.showMessageDialog(null, "The Server has just gone offline");
}
}
};
time.scheduleAtFixedRate(t, 0, 2000);
}
catch (Exception e1)
{e1.printStackTrace();
JOptionPane.showMessageDialog(null, "The Server is not online");}
}
});
bSend.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String textGekry = "what you are sending";
if (!textGekry.equals(""))
{
String sendMessage = textGekry + "\n";
try
{
bw.write(sendMessage);
bw.flush();
}
catch (Exception e1)
{
JOptionPane.showMessageDialog(null,"The Server is most likely offline");
}
}
}
});
I have a server app written in C# for Windows. I have a client app for android. I want to send data continuously from client to server in an infinite loop. The data is being sent but sometimes, there is a bad delay. I'm really stuck at it. Here's my client side code:
new Thread(new Runnable() {
public void run() {
Socket socket = null;
PrintWriter out = null;
while(true) {
try {
socket = new Socket(IP, PORT);
out = new PrintWriter(socket.getOutputStream(), true);
out.println(msg);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
Any idea why is there a delay?
Your problem is that you are initializing the socket every single iteration of your while loop.
new Thread(new Runnable() {
public void run() {
Socket socket = null;
PrintWriter out = null;
while(true) {
try {
socket = new Socket(IP, PORT);
out = new PrintWriter(socket.getOutputStream(), true);
out.println(msg);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
Refactor it out of the loop, like this:
new Thread(new Runnable() {
public void run() {
Socket socket = new Socket(IP, PORT);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while(true) {
try {
out.println(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}).start();
Unless that is by design, in which case, why?
It seems the code is correct. The lag may be caused not only by the application but also by the network status.
Try to ping to the router from both devices and see if you are having lag spikes due to the wireless conection. If you see high lag in pings the problem is in the connection, not in the application.
I'm trying to write an Android client and a Java server.
It works to send a message from the Android client to the server (if the testing code is commented out), but I cannot get the response back from the server to the client.
Could you please help me?
Here's the client:
public class MainActivity extends Activity {
private PrintWriter printwriter;
private EditText textField;
private TextView textView;
private Button button;
private String message;
private String serverResponse;
String fromServer;
Socket clientSocket;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textField = (EditText) findViewById(R.id.editText1);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button1);
final String hostName = "10.111.207.253";
final int portNumber = 4444;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
message = textField.getText().toString();
textField.setText("");
new Thread(new Runnable() {
public void run() {
try {
clientSocket = new Socket(hostName, portNumber);
printwriter = new PrintWriter(clientSocket.getOutputStream(),true);
printwriter.write(message);
// testing only - trying to get the response back from the server
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(true) {
if ((serverResponse = in.readLine()) != null) {
Log.i("server says", serverResponse);
break;
}
}
// testing only
printwriter.flush();
printwriter.close();
clientSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
textView.setText("Server: " + serverResponse);
}
});
}
}
And here's the server:
public class MyServer {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept(); //accept the client connection
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); //get the client message
message = bufferedReader.readLine();
if (message != null) {
System.out.println("Client says: " + message);
//testing only
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
out.println("response from server");
//testing only
inputStreamReader.close();
clientSocket.close();
}
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
}
}
Please help!
You've inserted code to read a reply from the server before you flush your client's PrintWriter. You're not using println() so the boolean you passed to the constructor to enable autoflush doesn't apply as stated in the javadoc:
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output. These methods use the platform's own notion of line separator rather than the newline character.
This means the client is never sending anything, therefore the server never receives anything. Back in the client you'll block forever waiting for a reply that is never coming.
Either use printwriter.println() to send your message, or move printwriter.flush() to before you attempt to read a reply from the server.
So, i have a Android-App(Client) and a Java-program(Server), with a One-time socket communication, whenever the android app connects to my server in a special activity (working fine).
Because my server is embedded in a bigger program (with Swing-components, where the server takes its informations from), i have this (reduced) code here:
//somewhere in my Swing-Application
Server myServer = new Server();
myServer.start();
//...
public class Server extends Thread {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8090);
try {
while (true) {
System.out.println("Server is waiting for connections...");
socket = serverSocket.accept();
startHandler(socket);
}
} finally {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void startHandler(final Socket socket) throws IOException {
System.out.println("Client connected to Server");
Thread thread = new Thread() {
#Override
public void run() {
try {
writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
//doing something usefull, i am sending a JSON-String, which i´ll parse in my app.
writer.write(someStringContainingJSONString);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeSocket();
}
}
private void closeSocket() {
try {
socket.close();
} catch (IOException e) {
}
}
};
thread.start();
}
In my Android-App i have:
public void onCreate(Bundle savedInstanceState) {
viewJSON = new Runnable() {
#Override
public void run() {
getJSON();
}
};
Thread thread = new Thread(null, viewJSON, "MagentoBackground");
thread.start();
myProgressDialog = ProgressDialog.show(myActivity.this, "Please wait...", "Retrieving data ...", true);
}
private void getJSON() {
try {
socket = new Socket(serverIPAddress, SERVER_PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String help = reader.readLine();
// parse this String according to JSON, is working fine!
}
// catch and so on...
Now, i want the app, to recieve data, whenever i hit a button "send data" from my Swing-Application, to have the newest data available.
On the other hand, i want the server to recieve data (also a JSON-String) when i make changes in my Android app. The String should also be send when i hit a specific button.
How can i do that? The problem is the threading issue(otherwise my swing application wouldn´t work) combined with networking. If i don´t close the socket, i cannot continue with my program properly (or at least, it seems so with my code right now)
Can you help me out here?
Thank you very much in advance for your help and thoughts.
Best, Andrea
I have an java application using Socket TCP/IP and GUI. Server always listens connection and receives message from client. When server received message, it will show a swing form.
My trouble is when I click on close button, the application will stop although I set server socket ALWAYS listens connection (by put method serverSocket.accept() in loop while(true)).
How can I solve that problem ?
Here is my code on Server:
public class TCPServer {
ServerSocket server = null;
BufferedReader in;
PrintWriter out;
Socket client = null;
//open serverSocket
public void openServer() {
try {
server = new ServerSocket(1234);
} catch (Exception e) {
e.printStackTrace();
}
}
//accept connection and read data
public void listening() {
try {
while (true) {
client = server.accept();
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
//read data from stream
String s = in.readLine();
System.out.println("String receive: " + s);
new NewJFrame().setVisible(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void closeServer() {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
if (client != null) {
client.close();
}
if (server != null) {
server.close();
}
} catch (Exception e) {
}
}
public static void main(String arg[]) {
TCPServer server = new TCPServer();
server.openServer();
server.listening();
server.closeServer();
}
}
From Javadoc:
EXIT_ON_CLOSE
The exit application default window close operation.
In the NewJFrame class, remove this: setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
This is making the whole application shutdown when the close button is hit!
Replace it by:
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
This way you are sure only the window is disposed, not the whole application
Can we guess that your Dialog has the "CLOSE_ON_EXIT" option set ot that it calls "System.exit()" directly?
If not, give more information.