Can't send / receive socket messages? - java

I am trying to programm a little chat console, because I've recently learned to work with ServerSocket and Sockets. But I have a problem, I am not receiving / sending any messages what am I doing wrong?
Class:Chatting (Main)
package chatting;
import java.util.Scanner;
public class Chatting {
public static Client client;
public static Server server;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Your username: ");
String name = sc.nextLine();
System.out.print("connect to: ");
String ip = sc.nextLine();
client = new Client(ip.split(":")[0], Integer.parseInt(ip.split(":")[1]), name);
while (true){
String chat = sc.nextLine();
client.send(chat);
}
}
}
Class:Client
package chatting;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Client {
Socket s;
public Client(String ip, int port, String name){
if (ip.equalsIgnoreCase("localhost")){
Chatting.server = new Server();
}
new Thread(new Runnable(){
#Override
public void run(){
try{
s = new Socket(ip, port);
System.out.println("CONNECTION >> Waiting for conformation with name "+name+"!");
send("#reg"+name);
WaitForMessage("#confirmed");
System.out.println("CONNECTION >> You have been registered to server!");
while (true){
List<String> recieve = recieve();
if (!recieve.isEmpty()){
for (String str : recieve){
System.out.println(str);
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
public void send(String msg){
try{
OutputStream os = s.getOutputStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(os), true);
pw.write(msg);
pw.flush();
}catch(Exception e){
e.printStackTrace();
}
}
public List<String> recieve(){
List<String> r = new ArrayList<String>();
try{
InputStream is = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine())!=null){
System.out.println("CRECIEVE >> "+line);
r.add(line);
}
}catch(Exception e){
e.printStackTrace();
}
return r;
}
public void WaitForMessage(String msg){
while (true){
if (recieve().contains(msg)) break;
}
}
}
Class:Server
package chatting;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Server {
ServerSocket ss;
List<Socket> s;
HashMap<String, String> registered;
public Server(){
s = new ArrayList<Socket>();
registered = new HashMap<String, String>();
try {
ss = new ServerSocket(1234);
System.out.println("SERVER >> created server on port 1234!");
} catch (IOException e) {
e.printStackTrace();
}
new Thread(new Runnable(){
#Override
public void run(){
while (true){
try{
Socket socket = ss.accept();
if (socket != null){
System.out.println("SERVER >> client connected "+socket.getLocalAddress().toString());
s.add(socket);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable(){
#Override
public void run(){
while (true){
for (Socket s : s){
List<String> result = translate(recieve(s));
if (!result.isEmpty()){
for (String str : result){
if (str.startsWith("#reg")){
str = str.replaceAll("#reg", "");
registered.put(s.getInetAddress().toString(), str);
System.out.println("SERVER >> user "+str+" on "+s.getLocalAddress().toString()+" registered!");
send(s, "#confirmed");
}else{
sendToAll(registered.get(s.getLocalAddress().toString())+" >> "+str);
}
}
}
}
}
}
}).start();
}
public void send(Socket s, String str){
try{
OutputStream os = s.getOutputStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(os), true);
pw.write(str);
pw.flush();
}catch(Exception e){
e.printStackTrace();
}
}
public List<String> translate(String[] str){
List<String> r = new ArrayList<String>();
for (String s : str){
r.add(s);
}
return r;
}
public String[] recieve(Socket s){
String[] r = null;
try{
ArrayList<String> lines = new ArrayList<String>();
InputStream is = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine()) != null) {
System.out.println("SRECIEVE >> "+line);
lines.add(line);
}
r = new String[lines.size()];
for (int i = 0; i < lines.size(); i++){
r[i] = lines.get(i);
}
}catch(Exception e){
e.printStackTrace();
}
return r;
}
public void sendToAll(String str){
for (Socket soc : s){
send(soc, str);
}
}
My problem is simply no messages get received / sent.
When I start the server it starts the client and connects perfectly, but when I get to
try{
s = new Socket(ip, port);
System.out.println("CONNECTION >> Waiting for conformation with name "+name+"!");
send("#reg"+name);
WaitForMessage("#confirmed");
System.out.println("CONNECTION >> You have been registered to server!");
while (true){
List<String> recieve = recieve();
if (!recieve.isEmpty()){
for (String str : recieve){
System.out.println(str);
}
}
}
}catch(Exception e){
e.printStackTrace();
}
Nothing happens anymore.

You're reading lines but you aren't writing lines. Use println() instead of write(). And fix everything that #PeterLawrey mentioned too. And if readLine() returns null, close the socket and stop reading.

Related

Java Sockets not connecting outside of the same Network

Hello I am having trouble with getting both the server and the clients connecting to each other when they are not on the same network. Please could you have a look at the code and see what I need to do to fix this issue.
I am new at Java and with the whole networking side of things so any help would be appreciated.
Server
>!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
public class ChatServer {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
// Create character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.add(out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException e) {
System.out.println(e);
} finally {
// This client is going down! Remove its name and its print
// writer from the sets, and close its socket.
if (name != null) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Client
>!
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatClient {
BufferedReader in;
PrintWriter out;
JFrame frame = new JFrame("Messager");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8, 40);
public ChatClient() {
// Layout GUI
textField.setEditable(false);
messageArea.setEditable(false);
frame.getContentPane().add(textField, "North");
frame.getContentPane().add(new JScrollPane(messageArea), "Center");
frame.pack();
// Add Listeners
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
}
/**
* Prompt for and return the address of the server.
*/
private String getServerAddress() {
return JOptionPane.showInputDialog(
frame,
"Enter IP Address of the Server:",
"Welcome to the Messager",
JOptionPane.QUESTION_MESSAGE);
}
/**
* Prompt for and return the desired screen name.
*/
private String getName() {
return JOptionPane.showInputDialog(
frame,
"Choose a screen name:",
"Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
/**
* Connects to the server then enters the processing loop.
*/
private void run() throws IOException {
// Make connection and initialize streams
String serverAddress = getServerAddress();
Socket socket = new Socket("86.190.97.107", 9001);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(getName());
} else if (line.startsWith("NAMEACCEPTED")) {
textField.setEditable(true);
} else if (line.startsWith("MESSAGE")) {
messageArea.append(line.substring(8) + "\n");
}
}
}
/**
* Runs the client as an application with a closeable frame.
*/
public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
Thanks for all of your answers i found out that the server needed to be hosted on a separate computer for the external IP to work.

socket not writing to server

There are question with the same problem but they are not helping me out.
Below is the code I've been working on where the ServerSocket not receiving any message from client Socket.
Server
package rescue_server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.TreeMap;
/**
*
* #author Mohammad Faisal
*/
public class RServer {
private TreeMap<String, PrintWriter> clients;
private static final int PORT = 6621;
private class ClientHandler implements Runnable {
private PrintWriter writer;
private BufferedReader reader;
public ClientHandler(Socket client) {
try {
writer = new PrintWriter(client.getOutputStream());
reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
#Override
public void run() {
System.out.println("client handler thread started");
String msg;
try {
while ((msg = reader.readLine()) != null) {
System.out.println(msg);
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
public RServer() {
clients = new TreeMap<>();
}
public void start() {
try {
ServerSocket server = new ServerSocket(RServer.PORT);
while (true) {
System.out.println("waiting....");
Socket client = server.accept();
Thread tclient = new Thread(new ClientHandler(client));
tclient.setDaemon(true);
tclient.start();
System.out.println("got a connection.");
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) {
new RServer().start();
}
}
Client
package rescue_client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
/**
*
* #author Mohammad Faisal
*/
public class RClient {
private final static int SERVER_PORT = 6621;
private final static String SERVER_IP = "127.0.0.1";
private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
private class ServerHandler implements Runnable {
#Override
public void run() {
System.out.println("server handler started.");
String msg;
try {
while ((msg = reader.readLine()) != null) {
System.out.println(msg);
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
public RClient() {
JFrame frame = new JFrame(SERVER_IP);
frame.setVisible(true);
frame.setBounds(10, 20, 100, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void startServerHandler() {
Thread tserver = new Thread(new ServerHandler());
tserver.setDaemon(true);
tserver.start();
sendWelcomeMsg();
}
private void sendWelcomeMsg() {
try {
writer.write(InetAddress.getLocalHost().getHostName());
writer.flush();
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
}
writer.flush();
}
public void start() {
System.out.println("starting client...");
try {
socket = new Socket(RClient.SERVER_IP, RClient.SERVER_PORT);
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
startServerHandler();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) {
new RClient().start();
}
}
The problem is I'm not getting the message on server from client.
From JavaDoc:
A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
So you have to add one of these in your String that is being sent.

Server program not sending data

I'm continuing work on an android app for my coworkers. I've gotten past the errors in my code, but a new problem has arisen. The server program is meant to read from a text file and send the data to an android app, which interprets the data and organizes it into a listview.
This is the code:
Bserver:
package beaconserver;
import java.io.*;
import java.net.*;
public class Bserver {
static ServerSocket Sock = null;
static Socket server = null;
public static void main(String[] args) {
BufferedReader in = null;
PrintWriter Out = null;
String ok;
try{
System.out.println("Waiting for connection");
while(true){
Sock = new ServerSocket(8006);
server = Sock.accept();
in = new BufferedReader(new InputStreamReader(server.getInputStream()));
Out = new PrintWriter(server.getOutputStream());
String input = null;
Bfile file = new Bfile();
String[] companies = file.get();
System.out.println("starting send");
while(true){
System.out.println("in the while loop");
ok=in.readLine();
Bprotocol protocol = new Bprotocol();
input = protocol.sendMessage(ok, companies );
Out.write(input);
if(input.equals("end")){
break;
}
}
System.out.println("out of the while loop");
Out.close();
in.close();
server.close();
Sock.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Bprotocol:
public class Bprotocol {
static String output = null;
static int count = 0;
public String sendMessage(String ok, String[] file){
if(ok!=null && count<file.length){
System.out.println(count+1 + "of" + file.length);
output = file[count];
count++;
}else if(ok==null && count<file.length){
output=null;
}else if (count==file.length){
output = "end";
}
return output;
}
}
Bfile:
package beaconserver;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class Bfile {
static String[] filenames;
static BufferedReader Br = null;
static String names = null;
static ArrayList<String> Names = new ArrayList<String>();
public String[] get(){
try {
Br = new BufferedReader(new FileReader("/home/kyle/Documents/names.txt"));
} catch (FileNotFoundException e) {
System.out.println("file not found");
e.printStackTrace();
}
try {
while(Br.ready()){
names = Br.readLine();
Names.add(names);
}
Br.close();
} catch (IOException e) {
System.out.println("IOexception");
e.printStackTrace();
}
filenames = new String[Names.size()];
filenames = Names.toArray(filenames);
return filenames;
}
}
MainActivity: android
package com.AWS.beacon;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity{
TextView response;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
response = (TextView) this.findViewById(R.id.textView2);
new GetNames(this).execute();
}
}
class GetNames extends AsyncTask<Void,String,Void>{
ArrayList<String> names = new ArrayList<String>();
PrintWriter out = null;
BufferedReader in = null;
Socket sock = null;
int L = 0;
String T = null;
static String[] companies = null;
String fromserver;
public MainActivity GetNamescontext =null;
public GetNames (MainActivity context){
GetNamescontext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
TextView prog = (TextView) GetNamescontext.findViewById(R.id.textView2);
prog.setText("Connecting");
}
#Override
protected Void doInBackground(Void... params) {
try {
sock = new Socket("elvishknight1.noip.me", 8006);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
out = new PrintWriter(sock.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
out.write("ok");
while((fromserver=in.readLine())!=null){
if(fromserver.equals("end")){
break;
}
T = in.readLine();
names.add(T);
}
out.close();
in.close();
sock.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
companies = names.toArray(new String[names.size()]) ;
Intent i = new Intent(GetNamescontext, MainScreen.class);
GetNamescontext.startActivity(i);
}
}
the program has some Sytsem.out.println commands for debugging. the problem is the program gets stuck on "in the while loop" and stops there. No errors, no logcat, nothing. I'm not sure what the problem could be. Could you guys help me out on this.
Thanks
You should add Out.flush() after Out.write(input);
When to use flush method and why do we use it?
this is used when there needs to be synchronous sending
for example you have a duplex (2-way) connection and you just sent a message and now need to wait for the reply on it, without flush a buffered outputstream might hold it until the buffer fills up (deadlock)
Temp Solution : i suppose you have defined in project's manifest that you need the internet permission. See this link
In your client you use readLine(). Therefore the server should write lines. Lines end with a \n. Especially send "end\n".

Java send to all sockets

Im making a chat program.
i got the client to server connection working but i cant get the server to send to all sockets. Since Im using ObjectOutputStream i cant use PrintWriter which was the way I did it before, Heres my code thanks for the help
Server
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
public Server clients[] = new Server[50];
public static String user;
private static final int PORT = 4000;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<>();
public static void main(String[] args) throws Exception{
System.out.println("The chatroom is running...");
ServerSocket listener = new ServerSocket(PORT);
try{
while(true){
new Handler(listener.accept()).start();
}
}
catch(Exception e){
System.err.println(e);
}
finally{
listener.close();
}
}
private static class Handler extends Thread{
private String name;
private Socket socket;
//private BufferedReader in;
//private PrintWriter out;
public ObjectOutputStream out;
public ObjectInputStream in;
public void send(Message msg) throws IOException{
out.writeObject(msg);
out.flush();
}
public void Announce(String type, String sender, String content){
Message msg = new Message(type, sender, content, "All");
}
public Handler(Socket socket){
this.socket = socket;
}
public void run(){
try {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = (new ObjectInputStream(socket.getInputStream()));
out.writeObject(new Message("SUBMITNAME", "blank", "blank", "blank"));
while(true){
Message msg = (Message) in.readObject();
if(msg.sender == null){
return;
}
if(!names.contains(msg.sender)){
names.add(msg.sender);
System.out.println(names.toString());
System.out.println("The object is " + msg);
}
break;
}
while(true){
Message msg = (Message) in.readObject();
System.out.println(msg);
names.add(msg.sender);
System.out.println(names.toString());
break;
}
//out.writeObject(new Message("MESSAGE", "Server", "Welcome To the ChatRoom", "c"));
while(true){
Message msg = (Message) in.readObject();
if(msg.type.equals("MESSAGE")){
out.writeObject(new Message("MESSAGE", msg.sender, msg.content, "all"));
System.out.println(msg.sender + ": " + msg.content);
}
}
}
catch (Exception e) {
System.err.println(e);
}
finally{
try{
socket.close();
System.out.println("Socket has closed");
}
catch(IOException e){
System.err.println("Problem closing socket!");
}
}
}
}
}
Client
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.DefaultCaret;
import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
public class Client implements Serializable{
//private BufferedReader in;
//private PrintWriter out;
ObjectOutputStream out;
ObjectInputStream in;
String name;
JFrame frame = new JFrame("Client Box");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8,40);
JScrollPane scroll = new JScrollPane(messageArea);
ArrayList<String> list = new ArrayList();
public Client(){
textField.setEditable(false);
messageArea.setEditable(false);
messageArea.setWrapStyleWord(true);
messageArea.setLineWrap(true);
DefaultCaret caret = (DefaultCaret) messageArea.getCaret();
caret.setUpdatePolicy(ALWAYS_UPDATE);
//frame.setLayout(new BorderLayout());
frame.getContentPane().add(textField, BorderLayout.SOUTH);
frame.getContentPane().add(scroll, BorderLayout.CENTER);
frame.pack();
textField.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
//Message msg = new Message("MESSAGE", name, textField.getText(), "all");
//out.writeObject(msg);
sendAll("MESSAGE", name, textField.getText());
textField.setText("");
}catch(IOException ex){System.err.println(ex.printStackTrace()};
}
});
}
public void sendAll(String type, String sender, String content) throws IOException{
Message msg = (new Message(type, sender, content, "all"));
out.writeObject(msg);
out.flush();
}
private String getName(){
return JOptionPane.showInputDialog(frame, "Your Screen Name?", "Please Enter Screen Name: "
, JOptionPane.PLAIN_MESSAGE);
}
private String getMessage(){
return JOptionPane.showInputDialog(frame, "Your message?", "Please Enter Screen Name: "
, JOptionPane.PLAIN_MESSAGE);
}
private void run() throws IOException, ClassNotFoundException{
//String address = getServerAddress();
Socket socket = new Socket("localhost", 4000);
in = (new ObjectInputStream(socket.getInputStream()));
out = new ObjectOutputStream(socket.getOutputStream());
Message temp = (Message) in.readObject();
if(temp.type.equals("SUBMITNAME")){
textField.setEditable(true);
name = getName();
sendAll(name, "a", " b");
}
while(true){
Message msg = (Message) in.readObject();
messageArea.append(msg.sender + ": " + msg.content + "\n");
}
}
public static void main(String[] args) throws ClassNotFoundException{
Client client = new Client();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setLocationRelativeTo(null);
client.frame.setVisible(true);
try {
try {
client.run();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

java.io.BufferedReader.readLine() is nonblocking

I have a problem with readLine() in Java. I have a server and a client. From client I want to send a message to the server. The problem is that first, the client has to insert a text into a JTextField and when presses send then server to read the input from client, but server doesn't wait the input from client but instead reads null. But I read that readLine() is blocked until it has something to read, why it's not happening in this case?
Here I connect to the server and create the JFrame
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class StartingPoint {
private static PrintWriter out;
private static BufferedReader in;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
connectToServer();
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public static void createAndShowGui() throws IOException {
View frame = new View(out, in);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void connectToServer() throws IOException {
String serverAddress = "127.0.0.1";
int PORT = 8100;
Socket clientSocket = null;
out = null;
in = null;
try {
clientSocket = new Socket(serverAddress, PORT);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Could not connect to the server \n" + e);
System.exit(1);
} finally {
if (out != null)
out.close();
if (in != null)
in.close();
if (clientSocket != null)
clientSocket.close();
}
}
}
Here is JFrame implementation:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class View extends JFrame {
private JButton button;
private JTextField field;
private JPanel gui;
public View(final PrintWriter out, final BufferedReader in) throws IOException {
button = new JButton("Send");
field = new JTextField();
gui = new JPanel(new GridLayout(1, 0, 10, 10));
gui.add(button);
gui.add(field);
add(gui);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
out.println(field.getText());
try {
System.out.println(in.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
Here is the server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer extends Thread {
public static final int PORT = 8100;
private static ServerSocket serverSocket = null;
private Socket clientSocket = null;
public void run() {
String receive, answer;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
receive = in.readLine();
System.out.println("[server]" + receive);
answer = "hello " + receive;
out.println(answer);
out.flush();
} catch (IOException e) {
System.err.println("IO error \n" + e);
} finally {
try {
clientSocket.close();
} catch (IOException e) {
System.err.println("Close socket error \n" + e);
}
}
}
public SimpleServer() throws IOException {
while (true) {
serverSocket = new ServerSocket(PORT);
try {
clientSocket = serverSocket.accept();
new Thread(this).start();
} finally {
serverSocket.close();
}
}
}
public static void main(String[] args) throws IOException {
SimpleServer server = new SimpleServer();
}
}
Your connectToServer() method opens a connection, creates streams and ... then closes them before returning. So of course, the server sees the close straight away, and returns null on the first readLine() call.
I suspect that you may have copied the "close in a finally block" pattern without understanding what it means. So I shall explain:
This is the normal pattern:
InputStream is = null;
try {
is = new FileInputStream(someFile);
// read the stream
} finally {
if (is != null) {
is.close();
}
}
The purpose of the code above is to ensure that the InputStream is always closed. Or more precisely, that it is always closed before the try/finally exits.
This is generally a good thing. But if the purpose of your code is to open some streams that is going to be used after this bit of code completes, then closing the stream here is self defeating.
InputStream is = null;
try {
is = new FileInputStream(someFile);
} finally {
if (is != null) {
is.close();
}
}
// read the stream ... OOOPS! We've already closed it!!
So to take this back to your original code, you need to move the try/finally/close stuff to the run method, something along these lines:
public void run() {
try {
connectToServer();
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null)
out.close();
if (in != null)
in.close();
if (clientSocket != null)
clientSocket.close();
}
}
You should also catch and (probably) ignore IOException that might be thrown by each close() call.
Javadoc for BufferedReader.readLine()
doesn't say anything like that:
Returns:
A String containing the contents of the line, not including
any line-termination characters, or null if the end of the stream has been reached
In your code you are opening a connection in connectToServer() and closing it, so server sees the end of stream

Categories