I have created a chat server which is multi threaded and as and when the clients connect it initiates a separate thread for them to communicate. The problem is the my server is not broadcasting messages received from one client to all the other clients connected and I simply do not know how to implement it.
Following is my code, feel free to edit:
The serverclass:
ArrayList<ServerThread> clientlist = new ArrayList();
Hashtable clientList = new Hashtable();
private static ArrayList<PrintWriter> writers = new ArrayList<PrintWriter>();
public ChatServer(JTextField jtfA, JTextField jtfB, JTextArea jtaA, JTextArea tapane3) {
// TODO Auto-generated constructor stub
address= jtfA;
GETPORT=jtfB;
PORT=Integer.parseInt(jtfB.getText());
displaytext=jtaA;
clientside=tapane3;
}
public void run() {
// TODO Auto-generated method stub
try {
InetAddress ad=InetAddress.getLocalHost();
String ip=ad.toString();
address.setText(string);
address.setEditable(false);
System.out.println("Server IP is: " + ad);
ss = new ServerSocket (PORT);
Socket cs = null;
while (true)
{
cs=ss.accept();
System.out.println("Connected"+clientlist);
ServerThread handler = new ServerThread(cs,displaytext,clientside,writers);
clientlist.add(handler);
handler.start();
System.out.println(writers);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getActionCommand().equals("DisConnect"))
{
try {
ss.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
The server thread class::
public class ServerThread extends Thread {
Socket client;
JTextArea display;
JTextArea clients;
ServerSocket server;
ArrayList<PrintWriter> writers ;
public ServerThread(Socket cs, JTextArea displaytext, JTextArea clientside, ArrayList<PrintWriter> writers) {
// TODO Auto-generated constructor stub
client=cs;
display=displaytext;
clients=clientside;
this. writers=writers;
}
public void run () {
try{
BufferedReader br = new BufferedReader(
new InputStreamReader(
client.getInputStream()));
PrintWriter pr = new PrintWriter(
new OutputStreamWriter(
client.getOutputStream()));
String clientMsg="";
boolean all;
do {
//read msg from client
clientMsg = br.readLine();
//display.setText(clientMsg);
System.out.println("Server Received: " + clientMsg);
pr.println(clientMsg);
display.append(clientMsg+"\n");
clients.append(clientMsg+"\n");
pr.flush();
} while((all=br.readLine() != null));
br.close();
pr.close();
while (true) {
String input = br.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + ": " + input);
}
}}
catch (UnknownHostException uhe){
System.out.println("Server issue");
}
catch (IOException ioe){
System.out.println("Server Error IO");
}
catch (Exception e){
System.out.println("Server Error General");
}}
}
Faulty do/while loop. You're throwing away every second line, and not detecting end of stream correctly. It should be:
while ((line = br.readLine()) != null)
Related
I am trying to make some sort of login system, but the server and client wont talk to each other. I am not quite sure why they wont talk to each other, but any help is appreciated.
P.S The port is correctly set up on my router.
Client
public class Clients implements Runnable
{
String ip = "localhost";
int port = 25565;
Socket client;
static Thread thread;
boolean setup = false;
BufferedReader br;
PrintWriter pw;
public static void main(String[] args)
{
thread = new Thread(new Clients());
thread.start();
}
public void run()
{
while(!setup)
{
try {
client = new Socket(ip,port);
setup = true;
} catch (IOException e) {
setup = false;
}
}
try {
br = new BufferedReader(new InputStreamReader(client.getInputStream()));
pw = new PrintWriter(client.getOutputStream(),true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pw.flush();
pw.write("client");
while(true);
}
}
Server
public class Server implements Runnable
{
int port = 25565;
String input;
ServerSocket server;
Socket clients;
BufferedReader br;
PrintWriter pw;
boolean setup = false;
static Thread thread;
public static void main(String[] args)
{
thread = new Thread(new Server());
thread.start();
}
public void run()
{
try {
server = new ServerSocket(port);
clients = server.accept();
br = new BufferedReader(new InputStreamReader(clients.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
System.out.println("getting input");
while((input = br.readLine()) != null)
{
System.out.println(input);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You should first do write and then flush
pw.write("client\n");
pw.flush();
Also place \n in the line that you are writing since in the client you are doing br.readline(). So it will wait till a new line is available.
I see two problems. The first is that pw.flush should be invoked after pw.write. The second is that the server is waiting on readLine(), which will only return when it encounters a line ending. You should change Clients to invoke pw.write("clients\n"), adding the newline.
I'm trying to write a Java server so that an Android client can send a string to it, and the server would reply with its own string. The first part of this works, where the client sends a string to the server, but the server sending a message to the does not work: the packet makes it out of the server, but the Android client does not pick it up. Does anyone have suggestions on how to fix this?
This entire process worked previously on a Python server, but I am changing to Java because of library support (Java has better support for NAT traversal)
Server (Java):
public class TCPServer implements Runnable {
private Thread t = null;
#Override
public void run() {
// TODO Auto-generated method stub
String receive;
String response = "1||2||3||4\n";
ServerSocket tcpServer = null;
Socket tcpClient = null;
try {
tcpServer = new ServerSocket(4999);
System.out.println(" TCP open for connections");
while(true) {
tcpClient = tcpServer.accept();
BufferedReader inStream = new BufferedReader(new InputStreamReader(tcpClient.getInputStream()));
receive = inStream.readLine();
System.out.println("Server <<< " + receive);
DataOutputStream outStream = new DataOutputStream(tcpClient.getOutputStream());
outStream.write(response.getBytes("UTF-8"));
outStream.flush();
System.out.println("Server >>> " + response);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException: " + e.toString());
} finally {
if (tcpServer != null) {
try {
tcpServer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException: " + e.toString());
}
}
if (tcpClient != null) {
try {
tcpClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException: " + e.toString());
}
}
}
}
public void start() {
// TODO Auto-generated method stub
if(t == null) {
t = new Thread(this);
t.start();
System.out.println("Start TCP Server");
}
}
}
Client (Android):
public class AsyncTCPSend extends AsyncTask<Void, Void, Void> {
String address = "";
String message = "";
String response = "";
AsyncTCPSend(String addr, String mes) {
address = addr;
message = mes + "\n";
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = null;
try {
socket = new Socket(address, 4999);
socket.getOutputStream().write(message.getBytes());
ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream writeIn = socket.getInputStream();
while((bytesRead = writeIn.read(buffer)) != -1) {
writeBuffer.write(buffer,0,bytesRead);
response += writeBuffer.toString("UTF-8");
}
} catch (UnknownHostException e){
e.printStackTrace();
response = "Unknown HostException: " + e.toString();
System.out.println(response);
} catch (IOException e) {
response = "IOException: " + e.toString();
System.out.println(response);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
recieve.setText(response);
super.onPostExecute(result);
}
}
I don't know why you would call an InputStream 'writeIn', but the problem is that the client is reading the socket until end of stream, and the server is never closing the accepted socket, so end of stream never occurs.
this is a simple chat server and client i got from a book i've been reading and I'm having trouble understanding some of the code, can someone please help me with this problem
this is the client code here
public class ChatClient {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;
public static void main(String[] args) {
ChatClient client = new ChatClient();
client.go();
}
public void go() {
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
incoming = new JTextArea(15, 50);
incoming.setLineWrap(true);
incoming.setWrapStyleWord(true);
incoming.setEditable(false);
JScrollPane qScroller = new JScrollPane(incoming);
qScroller
.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
qScroller
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
outgoing = new JTextField(20);
JButton sendButton = new JButton("send");
sendButton.addActionListener(sendButtonListener);
mainPanel.add(qScroller);
mainPanel.add(outgoing);
mainPanel.add(sendButton);
setUpNetworking();
Thread readerThread = new Thread(new IncomingReader());
readerThread.start();
frame.add(mainPanel);
frame.setSize(400, 500);
frame.setVisible(true);
}
private void setUpNetworking() {
try {
sock = new Socket("127.0.0.1", 5000);
InputStreamReader streamReader = new InputStreamReader(
sock.getInputStream());
reader = new BufferedReader(streamReader);
writer = new PrintWriter(sock.getOutputStream());
System.out.println("connected");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ActionListener sendButtonListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
writer.println(outgoing.getText());
writer.flush();
outgoing.setText("");
outgoing.requestFocus();
}
};
public class IncomingReader implements Runnable {
#Override
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
incoming.append(message + "\n");
}
System.out.println("ggggggggg");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
the part that I'm having trouble understanding is this one:
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
incoming.append(message + "\n");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
in this part there is while code that is running as long as what we read from the server is not Null, my questions is won't the first thing that we read from the server as soon as we start the thread would be Null since we haven't written any thing to it yet, thus, breaking out of the loop?
like when would message equals Null?
this is the server code to whome ever wants to read it
public class ChatServer {
ArrayList clientOutputStreams;
public class ClientHandler implements Runnable {
BufferedReader reader;
Socket sock;
public ClientHandler(Socket clientSocket) {
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(
sock.getInputStream());
reader = new BufferedReader(isReader);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
tellEveryone(message);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
new ChatServer().go();
}
public void go() {
clientOutputStreams = new ArrayList();
try {
ServerSocket serverSock = new ServerSocket(5000);
while (true) {
Socket clientSocket = serverSock.accept();
PrintWriter writer = new PrintWriter(
clientSocket.getOutputStream());
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
System.out.println("got a connection");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void tellEveryone(String message) {
Iterator it = clientOutputStreams.iterator();
while (it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
a way that would be more logical to me would be having a while true loop and checking the server all the time waiting for a message like this:
while(true){
if ((message = reader.readLine()) != null){
System.out.println("read " + message);
incoming.append(message + "\n");
}
}
won't the first thing that we read from the server as soon as we start the thread would be Null since we haven't written any thing to it yet
I think you've answered your own question, in part. null is returned from BufferedReader#read when it reaches the EOF, so, since EOF marker hasn't been reached, the read method will block until either there is something to be read or EOF is reached.
From the JavaDocs...
public String readLine()
throws IOException
Reads a line of text. 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.
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
The loop is actually infinite. The only way this will break is if the underlying stream is closed, which is likely to cause an IOException
What book did you get this from? It's not a very good example
I have a Java Server and one(or more) Android Clients. For now I want them to communicate simply with strings. When i write from android I can get the data in Java Server, but when I try to get the answer from server the Android application stop working. The codes is reported below:
Java Server:
public class Server {
private static int port=12346, maxConnections=0;
// Listen for incoming connections and handle them
public static void main(String[] args) {
int i=0;
try{
ServerSocket listener = new ServerSocket(port);
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)){
doComms connection;
server = listener.accept();
String end = server.getInetAddress().toString();
System.out.println("\n"+end+"\n");
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}
class doComms implements Runnable {
private Socket server;
private String line,input;
public doComms(Socket server) {
this.server=server;
}
#SuppressWarnings("deprecation")
public void run () {
input="";
try {
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(server.getOutputStream())),
true);
while((line = in.readLine()) != null && !line.equals(".")) {
input=input + line;
}
JOptionPane.showMessageDialog(null, input);
out.println("Enviado");
server.close();
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
And Android client's code (it's called every time a button is pressed inside onClick method):
public String enviaMensagem(){
String resposta="";
new Thread(new ClientThread()).start();
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(ip, port);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(input.getText().toString());
resposta = dataInputStream.readUTF();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if (socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return resposta;
}
You are using an unsorted mixture of readUTF(), writeUTF(), readLine(), etc. They're not all interoperable. Settle on one of them. If you use writeUTF() you must use readUTF() at the other end. If you use readLine() you must write lines at the other end, with a line terminator such as \r\n or \n.
When ever I run the client after running the server, the server crashes with the error connection reset... here is my code:
initiate a client socket and connect to the server. wait for an input.
Client:
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private String fromServer,fromUser;
public ClientTest() {
try {
socket = new Socket("127.0.0.1", 25565);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() {
try {
while ((fromServer = in.readLine()) != null) {
System.out.println(fromServer);
out.println("1");
}
System.out.println("CLOSING");
out.close();
in.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new ClientTest();
}
initiate a server socket and send a "2" to client and initiate a conversation
Server:
public ServerTest() {
try {
serverSocket = new ServerSocket(25565);
clientSocket = serverSocket.accept();
}
catch (IOException e) {
System.out.println("Could not listen on port: 4444");
System.exit(-1);
}
start();
}
public void start() {
try {
PrintWriter out;
out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in;
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;
// initiate conversation with client
out.println("2");
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
out.println("2");
}
System.out.println("Stopping");
out.close();
in.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new ServerTest();
}
when ever I run the server everything is fine but when I run the client after that the server crashes with connection reset error.
ClientTest() does not call the start() method. Your client exits immediately after establishing the connection.
Alex's answer is right.
This program also goes to infinite loop. You need to add an exit condition in the while loop of client and server.