I'm creating chat program. At first, I send message to server from client and server should get message, but the message is not sent to the server until I shut down client.
Here is my code:
Client:
private Socket Client;
private Thread RunClient;
private JButton Send;
private int Port=8000;
private String Host="localhost";
public void init() {//Here we connecting to server
Send=new JButton();
Send.setFont(new Font("Times New Roman", Font.BOLD, 15));
Send.setLocation(575,Text.getHeight()+15);//395
Send.SetBorderColor(Color.cyan);
Send.setForeground(Color.white);
Send.setText("Send");
Send.setSize(30,70);
Send.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SendButton_Click(e);
}
});
try
{
InetAddress address = InetAddress.getByName(Host);
Client = new Socket(address, Port);
System.out.println("Client started. Port: "+Port+"\n");
}catch(Exception e){
System.out.println("Error:"+e);
}
}
public void SendButton_Click(ActionEvent e) {//Here we sending message to server
String sendMessage = "hi";
try {
sendMessageToServer(Client,sendMessage);//sending message to server
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("Message sent to the server : "+sendMessage);
}
}
private void sendMessageToServer(Socket socket,String message) throws IOException {
BufferedWriter writer = new BufferedWriter(new
OutputStreamWriter(socket.getOutputStream()));
writer.write(message);
writer.flush();
}
Here is server:
private int Port=8000;
public void init() {//Here we starting server and starting thread
try {
serverSocket = new ServerSocket(Port);
System.out.println("Server on. Port: "+Port+"\n");
} catch (IOException e1) {
e1.printStackTrace();
}
RunServer = new Thread() {
public void run() {
ServerLoop();
}
};
RunServer.start();
}
public void ServerLoop() {//here we should receive message..
while(true) {
System.out.println("Server loop");
try
{
Socket clientSocket = serverSocket.accept();
InputStreamReader inputstreamreader = new
InputStreamReader(clientSocket.getInputStream());
BufferedReader bufferedreader = new
BufferedReader(inputstreamreader);
PrintWriter printwriter = new
PrintWriter(clientSocket.getOutputStream(),true);
String line = "";
boolean done = false;
while (((line = bufferedreader.readLine()) != null) &&(!done)){
System.out.println("Received from Client: " + line);
if (line.compareToIgnoreCase("Exit") == 0) done = true;
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
Your server is waiting for a full line, i.e. a String that is terminated with \r, \n, or both. Your client does not send a line ending, thus the server's call to readLine() cannot complete until the stream ends, when the remaining (non-line-terminated) input is returned.
Try sending "hi\n" and it should work.
The readLine() method will wait until it receives a newline character (\n) before returning. This means that the method blocks until the client is disconnected. The solution is simple; change the line in sendMessageToServer() that is
writer.write(message);
to
writer.write(message + "\n");
However, you will not be able to send the server messages containing \n without bugs. To do so, you will have to rewrite your reading code to use character-by-character reading.
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 TCP Client in java and TCP server in android. Sending message form Server to Client works fine but when message is sent from Client to server(android) it doesn't shows the message but when same process is repeated second time, server shows the message i.e send button of java client should be pressed twice then only message is shown in the android app.
Java Client Code
//btn handelar to send message form textarea
private class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
String outputLine = txArea.getText ();
System.out.println ("Client > " + outputLine);
out.println (outputLine);
out.flush();
}
}
//receiving message
public void run () throws IOException
{
Socket socket = new Socket ("192.168.123.3",1234);
BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
out = new PrintWriter (socket.getOutputStream (), true);
String inputLine;
while ((inputLine = in.readLine ()) != null)
{
System.out.println ("Client < " + inputLine);
rxArea.setText (inputLine);
}
out.close();
in.close();
socket.close();
}
Android Server Code
public void runTcpServer(){
handel = new Handler();
try {
int a = Integer.parseInt(new SettingDialog().port);
//creating a socket to listen on a given port
Log.i("NW LOG","PORT OPENED SUCESSFULLY in "+a);
final ServerSocket serverSocket = new ServerSocket(a);
Thread listenConnection = new Thread(new Runnable() {
#Override
public void run() {
try {
//accepting the incoming socket connection request
Socket workstationSocket = serverSocket.accept();
//reading the incoming content
BufferedReader readerIn = new BufferedReader(new InputStreamReader(workstationSocket.getInputStream()));
outMessage = new PrintStream(workstationSocket.getOutputStream(),true);
Log.i("NW LOG","WATING FOR MSG");
while(readerIn.readLine()!=null){
final String incomingMsg = readerIn.readLine();
//setting incoming message to UI thread using handler
handel.post(new Runnable() {
#Override
public void run() {
setMessage(IN,incomingMsg);
}
});
}
outMessage.close();
readerIn.close();
workstationSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});listenConnection.start();
} catch (IOException e) {
e.printStackTrace();
}
}
The problem is the following code part:
while(readerIn.readLine()!=null){
final String incomingMsg = readerIn.readLine();
....
In the first line you are reading the line and ignoring it. Therefore you are throwing away every second line.
The correct way to read and use it for the while loop is this:
String incomingMsg;
while((incomingMsg = readerIn.readLine())!=null){
....
}
I have a socket client sending text to a socket server but the ReadLine doesnt seem to wait to receive a line before proceeding. Here is the of the server receiving the text:
public void run() {
try {
serveurSocket = new ServerSocket(PORT_ID);
connexionSocket = serveurSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(connexionSocket.getInputStream()));
PrintWriter writer = new PrintWriter(connexionSocket.getOutputStream(), true);
messageRecu = "";
while (true) {
messageRecu = reader.readLine();
messageRecu = messageRecu.toUpperCase();
writer.println(messageRecu);
}
//reader.close();
//writer.close();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
After establishing the socket between client and server, the execution halts at reader.readLine until I send manually a string thru the socket. Which is normal and wanted. Codes resumes and its fine until its loops back to reader.ReadLine() where it will read a "null" line instead of waiting for input from the socket like it did the first time... this will obviously mess up the next command to uppercase. So how can I fix this?
EDIT: I'll add the client side if that can help understand.
public class ClientSocket {
private Socket clientSocket;
public boolean isClosed() { return clientSocket.isClosed(); }
public boolean connectToSocket (String ip, int port) {
try {
clientSocket = new Socket(ip, port);
return true;
}
catch (IOException e) {
System.out.println(e);
return false;
}
}
public String sendToServer(String messageClient) {
String messageRecu = "";
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);
writer.println(messageClient);
messageRecu = reader.readLine();
reader.close();
writer.close();
return messageRecu;
}
catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return messageRecu;
}
}
}
A button press will call "connectTosocket" to initiate the socket. A second button when pressed will send the content of a textfield using "sendToServer".
Server does receive the message and return it capitalized but I wish for the socket to remain open with the server and if I send an other string for the same sequence to happen. Not even sure it can be done :(
According to the documentation of BufferedReader#readLine, a null is returned if the end of stream has been reached.
Change your reading loop to :
while ((messageRecu = reader.readLine()) != null) {
messageRecu = messageRecu.toUpperCase();
writer.println(messageRecu);
}
//Get out of the loop when the end of stream is reached.
As per Reading from and Writing to a Socket chapter of the Java tutorial.
As a side note, while(true) loops are not really appreciated.
The "null" signals for end of connection from the client side - which is why the connection disconnects. If you want to support multiple requests, you should run a new ServerSocket.accept() each time and wait for a new client to connect.
KKMultiServer class:
import java.net.*;
import java.io.*;
public class KKMultiServer {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java KKMultiServer <port number>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
while (listening) {
new KKMultiServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
}
}
}
KKMultiServerThread class:
import java.net.*;
import java.io.*;
public class KKMultiServerThread extends Thread {
private Socket socket = null;
public KKMultiServerThread(Socket socket) {
super("KKMultiServerThread");
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye"))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can read more about sockets in Oracle tutorials
I am trying to write a small program, that opens a server, creates a client that connects to this server and receives a message from it.
This is the Code so far
public static void main(String[] args) {
final ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(12345);
Thread t = new Thread(){
public void run(){
try {
Socket server = serverSocket.accept();
PrintWriter writer = new PrintWriter(server.getOutputStream(), true);
writer.write("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t.start();
Socket client = new Socket("localhost", 12345);
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String message = reader.readLine();
System.out.println("Received " + message);
} catch (IOException e1) {
e1.printStackTrace();
}
}
If i run program it keeps waiting in readLine() - so obviously the client does not receive the message from the server.
Has anyone got an idea why this isn' working?
Your reading thread is waiting for a newline in the data stream. Just change the server to use:
writer.write("Hello World\r\n");
and you'll get the result you were expecting. Alternatively, you can just close the server socket, and then readLine will return when it reaches the end of the data stream.
You should put the readline in a loop as follows:
public static void main(String[] args) {
final ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(12345);
Thread t = new Thread() {
public void run() {
try {
Socket server = serverSocket.accept();
PrintWriter writer = new PrintWriter(server.getOutputStream(), true);
writer.write("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t.start();
Socket client = new Socket("localhost", 12345);
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
// Check this --------------------------------------------------->
String message = null;
while ((message = in.readLine()) != null) {
System.out.println("Received " + message);
break; //This break will exit the loop when the first message is sent by the server
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
You can read this documentation for further explanation: http://download.oracle.com/javase/tutorial/networking/sockets/
I have a problem with my Java program. It has a socket connection between a server and many client. Here is the server (the part which concerns the problem):
private static ArrayList<ParallelServer> clientConnected = new ArrayList<ParallelServer>();
public Server(int port) {
this.port = port;
if (!startServer())
JOptionPane.showMessageDialog(new JFrame(""),
"Error!", "ERROR!",
JOptionPane.ERROR_MESSAGE);
}
private boolean startServer() {
try {
server = new ServerSocket(port);
loadDatabase();
} catch (IOException ex) {
ex.printStackTrace();
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return true;
}
public void runServer() {
while (true) {
try {
client = server.accept();
ParallelServer pServer = new ParallelServer(client);
clientConnected.add(pServer);
Thread thread = new Thread(pServer);
thread.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void sendBroadcast(String username) throws IOException {
for(int i = 0; i < clientConnected.size(); i++)
clientConnected.get(i).sendAnswer("#change," + username);
}
The parallel server is:
private Socket client;
private InputStreamReader inputstreamreader;
private BufferedReader bufferedreader;
private PrintWriter printwriter;
public ParallelServer(Socket client) {
this.client = client;
}
public void run() {
try {
inputstreamreader = new InputStreamReader(client.getInputStream());
bufferedreader = new BufferedReader(inputstreamreader);
printwriter = new PrintWriter(client.getOutputStream(), true);
String lineread = "";
while (client.isConnected()) {
lineread = bufferedreader.readLine();
doCommand(lineread);
}
} catch (UnknownHostException unhe) {
} catch (InterruptedIOException intioe) {
} catch (IOException ioe) {
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void sendAnswer(String answer) throws IOException {
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.println(answer);
printwriter.flush();
}
And here is the client:
private String serverurl = "localhost";
private int serverport = 7777;
private PrintWriter printwriter;
private InputStreamReader inputstreamreader;
private BufferedReader bufferedreader;
private Socket server;
public Client() {
server = null;
try {
server = new Socket(serverurl, serverport);
server.setSoTimeout(5000);
} catch (UnknownHostException unhe) {
System.out.println("UnknownHostException: " + unhe.getMessage());
} catch (InterruptedIOException intioe) {
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROE!",JOptionPane.ERROR_MESSAGE);
}
}
public String sendCommand(String command) throws IOException {
if(server == null) {
try {
server = new Socket(serverurl, serverport);
server.setSoTimeout(5000);
} catch (UnknownHostException unhe) {
System.out.println("UnknownHostException: " + unhe.getMessage());
} catch (InterruptedIOException intioe) {
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROR!",JOptionPane.ERROR_MESSAGE);
}
}
if(server != null) {
printwriter = new PrintWriter(server.getOutputStream(), true);
printwriter.println(command);
printwriter.flush();
inputstreamreader = new InputStreamReader(server.getInputStream());
bufferedreader = new BufferedReader(inputstreamreader);
return bufferedreader.readLine();
}
else
return "#serverProblem";
}
The program is a simple online game with turns. Players' turns are created with a queue and when a player passes his turn, the server send a broadcast message which say "Now it is 'Player 1' turn." (for instance). My problem is that when a client receive the message, its like it add the answer "Now it is 'Player 1' turn." to the next message it will receive. In my case: when a player passes his turn, he sends "#passTurn,username". The ParallelServer class polls it from the queue, puts it at the bottom of the queue, sends the client "#ok" to tell it that the turn has changed successfully and tells the Server class to send the broadcast message. Then, when the same client will try do do a further action, it will consider "Now it is 'Player 1' turn." as the answer the server has given to it. Instead, I would like that the server and the clients work as always and when the broadcast message is cought, the client is notified without any collateral effect.
What can I do?
Thanks.
Your bi-directional message passing mechanism should look something like this:
Server:
Wait on any client InputStream
if (broadcast)
broadcast_message()
else
process_message()
Client:
Receiving Thread:
Wait on server broadcast
Sending Thread:
Wait on messages to be sent to server from the User Input
This should do the trick :)
Hope it helps. Cheers!