I am trying to work with sockets in android programming, sending to the server works fine but i have problems with receiving a string from the server.
the socket is connected, but if the server is sending a string the android app only prints out: java.io.BufferedReader#418daee0
i dont know what that mean..is it an error or something like that?
this is my code:
Maybe someone could help me a little bit to get that work.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class Client extends Activity {
private Socket socket;
private static final int SERVERPORT = 2000;
private static final String SERVER_IP = "192.168.1.1";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String test = br.toString();
TextView message = (TextView) findViewById(R.id.received);
message.setText(test);
//in.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
what you need to do is read from the BufferedReader. Currently you are just printing the br object.
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = br.readLine ()) != null) {
System.out.println (line);
}
as per the javadocs readLine will return null if the end of the stream has been reached
problem:
String test = br.toString();
You are basically referencing the memory location in string form of the br object thus printing the memory location in your TextView. What you need to do is to read the inputStream from the socket connection of the server from your BufferedReader object.
solution:
String test = br.readLine();
The readLine method will wait for the response of the server from the InputStream where the socket is connected. Now the above will only get one line of response from the server if the server sends multiple line then you put it in a while loop.
Related
I want to send arraylist on multithreading server to client . So far i just write the conection and the clients can write and send to server msg ,the server just send back the msg to client is write somathing just sending. My main problems is how to transfer from server to client the arraylist ?
i am new on this and i dont know nothing for arralist .
code server :
import java.io.*;
import java.net.*;
import java.util.ArrayList;
// Server class
class Server {
public static void main(String[] args)
{
private ArrayList<Objects> Obj = new ArrayList<Objects>();
// file read
// String filePath = "Hotels_new.txt";
// System.out.println(Read_File( filePath ));
ServerSocket server = null;
try {
// server is listening on port 1234
server = new ServerSocket(1234);
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to server
System.out.println("New client connected" + client.getInetAddress().getHostAddress());
// create a new thread object
ClientHandler clientSock = new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (server != null) {
try {
server.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static String Read_File(String filePath)
{
// Declaring object of StringBuilder class
StringBuilder builder = new StringBuilder();
// try block to check for exceptions where
// object of BufferedReader class us created
// to read filepath
try (BufferedReader buffer = new BufferedReader(
new FileReader(filePath))) {
String str;
// Condition check via buffer.readLine() method
// holding true upto that the while loop runs
while ((str = buffer.readLine()) != null) {
builder.append(str).append("\n");
}
}
// Catch block to handle the exceptions
catch (IOException e) {
// Print the line number here exception occurred
// using printStackTrace() method
e.printStackTrace();
}
// Returning a string
return builder.toString();
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket socket)
{
this.clientSocket = socket;
}
public void run()
{
PrintWriter out = null;
BufferedReader in = null;
try {
// get the outputstream of client
out = new PrintWriter( clientSocket.getOutputStream(), true);
// get the inputstream of client
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
// writing the received message from
// client
System.out.printf(" Sent from the client: %s\n",line);
out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (out != null) {
out.close();
}
if (in != null)
{
in.close();
clientSocket.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
code client:
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.ArrayList;
// Client class
class Client {
// driver code
public static void main(String[] args)
{
// establish a connection by providing host and port
// number
try (Socket socket = new Socket("localhost", 1234)) {
// writing to server
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
// reading from server
BufferedReader in
= new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// object of scanner class
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
// reading from user
line = sc.nextLine();
// sending the user input to server
out.println(line);
out.flush();
// displaying server reply
System.out.println("Server replied "
+ in.readLine());
}
// closing the scanner object
sc.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
In order to send something more complex you will have to serialize it. You can choose how to do the serialization, maybe the easiest is to use ObjectOutputStream and ObjectInputStream on the server and client respectively. These can be used very similarly to the PrintWriter / BufferedReader solution you are doing now.
I had to change a few things as your example code did not compile.
Example server based on your code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
public class Server {
private static final List<Integer> myIntArray = List.of(1, 2, 3);
public static void main(String[] args) {
ServerSocket server = null;
try {
// server is listening on port 1234
server = new ServerSocket(1234);
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to server
System.out.println("New client connected" + client.getInetAddress().getHostAddress());
// create a new thread object
ClientHandler clientSock = new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
public void run() {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(clientSocket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
while (in.readLine() != null) {
objectOutputStream.writeObject(myIntArray);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Example client:
import java.io.*;
import java.net.*;
import java.util.*;
// Client class
class Client {
// driver code
public static void main(String[] args) {
// establish a connection by providing host and port
// number
try (Socket socket = new Socket("localhost", 1234);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
// object of scanner class
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
// reading from user
line = sc.nextLine();
// sending the user input to server
out.println(line);
out.flush();
// displaying server reply
List<Integer> integers = (List<Integer>) ois.readObject();
System.out.println("server: " + integers.get(0));
}
// closing the scanner object
sc.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Keep in mind that if you are about to send your own custom types, both sides will have to know about those to be able to serialize/deserialize. Also, your classes will have to be serializable.
I am getting started with java sockets just out of inquisitiveness.
I wrote a small piece of code, a server and a client.
The server accepts a string and converts it to upper case and returns to the client.
I want the server to be able to handle multiple clients and have a persistent connection.
Here is the server code :
package 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.net.SocketException;
import java.util.ArrayList;
public class Server {
private ServerSocket listener;
private ArrayList<Socket> clients;
public Server() throws IOException{
clients = new ArrayList<Socket>();
listener = new ServerSocket(7575);
}
public Server(int port) throws IOException{
clients = new ArrayList<Socket>();
listener = new ServerSocket(port);
}
public void start() throws IOException, InterruptedException{
Thread one = new Thread(){
public void run(){
while (true){
Socket socket = null;
try {
socket = listener.accept();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (socket.isConnected()){
try {
socket.setKeepAlive(true);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clients.add(socket);
System.out.println(socket.getRemoteSocketAddress().toString());
}
}
}
};
Thread two = new Thread(){
public void run(){
try {
while (true){
work();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
one.start();
two.start();
one.join();
two.join();
stop();
}
private void stop() throws IOException{
listener.close();
}
private void work() throws IOException{
if (clients.size() == 0){
return;
}
for(int i = 0; i < clients.size(); i++){
Socket socket = clients.get(i);
if (!socket.isClosed()){
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String data = br.readLine();
if (data == null) continue;
out.println(data.toUpperCase());
}
else{
clients.remove(socket);
}
}
}
}
package entry;
import java.io.IOException;
import server.Server;
public class Main {
public static void main(String args[]) throws IOException{
Server server = new Server();
try {
server.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
and here is the client :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Main {
public static void main(String args[])throws IOException{
Socket socket = new Socket("192.168.0.110", 7575);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader sr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pr = new PrintWriter(socket.getOutputStream(), true);
while (true){
System.out.println("\n\nEnter a string : ");
String inp = br.readLine();
if (inp.equals("quit")) break;
pr.println(inp);
System.out.println("The response is : " + sr.readLine());
}
socket.close();
}
}
Strange thing here is when I set a breakpoint in the server code and step through the code in eclipse, the code is working exactly as expected i.e I am getting the response in the client.
But when I run it directly in eclipse, I am not getting the response in the client.
Cannot understand what is going wrong.
Edit
I seem to have fixed the issue.
Here is the code snippet :
Thread two = new Thread(){
public void run(){
try {
while (true){
Thread.sleep(1000); //This is the added line
work();
}
} catch (IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
But I am still confused about what made the timing difference.
Is there any cleaner way to achieve this ?
I've solved the problem with a different approach.
Here is the new Approach:
ServerHandler.java :
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
public class ServerHandler extends Thread{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private ArrayList<Socket> clients;
public ServerHandler(Socket socket) throws IOException{
this.socket = socket;
clients = new ArrayList<Socket>();
if (!clients.contains(socket)){
clients.add(this.socket);
System.out.println(this.socket.getRemoteSocketAddress());
}
}
#Override
public void run(){
while (true){
if (clients.isEmpty()) break;
String str = null;
for (int i = 0; i < clients.size(); i++){
Socket socket = clients.get(i);
if (socket.isClosed()){
clients.remove(socket);
continue;
}
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
out = new PrintWriter(socket.getOutputStream(), true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
str = in.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.println(str.toUpperCase());
}
}
}
}
Main.java [for running the server] :
package entry;
import java.io.IOException;
import java.net.ServerSocket;
import server.ServerHandler;
public class Main {
public static void main(String args[]) throws IOException{
ServerSocket listener = new ServerSocket(7575);
try{
while (true){
new ServerHandler(listener.accept()).start();
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
listener.close();
}
}
}
Ok, Here we go.I don't understand the use of Arraylist for maintaining Connections unless You are handling the messy details for each Client.
The most used or prefered approach for handling multiple clients at a time can be understood in terms of an example:
Server.java
import java.net.ServerSocket;
import java.io.IOException;
class Server {
public static void main(String[] args) throws IOException {
try( ServerSocket ss = new ServerSocket(3333)) { // try with resources
new ServerThread(ss.accept()).start();
}
}
}
As you can see, I just defined a Class that will listen for Client connections, and as soon a request is made to the server it will start a Thread which is defined in the next class. A point to be noted here is the use of Try-with-Resources block. Any class that implements the Closeable interface can be enclosed within this try statement. The try-with-resources automatically handles closing of streams or connections for me. This means, you remove all your redundant try-catch blocks from your code and use this try instead.
Now,
ServerThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerThread extends Thread {
Socket s = null;
public ServerThread(Socket s) {
super("ServerThread");
this.s = s;
}
public void run() {
try( PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
BufferedReader stream = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedReader write = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("In Server");
String in, out;
while ((in = stream.readLine()) != null) {
System.out.println("Msg 4m client: " + in);
if(in.equals("bye"))
break;
out = write.readLine();
pw.println(out);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Observe the try-with-resources statement over here, We can initialize multiple Connections/Input-Output Streams here, All of the opened connection will automatically be closed as soon as the compiler returns from try statement.Also, Observe the while statement, it will keep on running until the client is sending messages, and will quit if the message is "bye".
Finally, a Client program that sends request to the server.
Client.java
import java.net.Socket;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
class Client {
public static void main(String[] args) {
try( Socket s = new Socket("localhost", 3333);
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
BufferedReader stream = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedReader write = new BufferedReader(new InputStreamReader(System.in)) ) {
System.out.println("In Client");
String in;
while ((in = write.readLine()) != null) {
pw.println(in);
if(in.equals("bye"))
break;
System.out.println("Msg 4m server: " + stream.readLine());
}
} catch(IOException e) {
System.err.println("Exception: " + e);
}
}
}
Notice, the while Statement here, it will loop until the user is entering messages, and if the message is "bye", it will quit.Rest of the program can be easily understood from above explanation.
I am beginner to java and learning Socket Programming.I am using the basic chat server socket communication. I am having difficulty to print the server and client messages to the console window.
I would also implement this concept when i design my chat Server window UI and will update the char server intercommunication messages to my UI. I would like to know as how can I achieve that ?
Code for 1
Server.java
package ChApp;
import java.io.IOException;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
Socket s;
ServerSocket server = new ServerSocket(3900);
while(true)
{
s = server.accept();
ServerHandl handle1 = new ServerHandl(s);
Thread t1= new Thread(handle1);
t1.start();
System.out.println("Connection Succesful...");
server.close();
}
}
}
Serverhandl.java
package ChApp;
import java.io.*;
import java.net.*;
public class ServerHandl implements Runnable {
Socket s= null;
BufferedReader read;
PrintWriter write;
String msg="Server is sending a sample msg";
public ServerHandl(Socket s)
{
this.s = s;
}
public void run()
{
try {
write = new PrintWriter(s.getOutputStream());
write.println(msg);
read = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(read.readLine());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
read.close();
write.close();
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Client.java
package ChApp;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
Socket s= null;
BufferedReader read;
PrintWriter write = null;
String h;
StringBuilder sb = new StringBuilder();
String sendmsg="Reply from client";
s= new Socket("localhost",3900);
read = new BufferedReader(new InputStreamReader(s.getInputStream()));
while((h=read.readLine())!=null)
{
sb.append(h);
}
write = new PrintWriter(s.getOutputStream(),true);
write.write(sendmsg);
write.flush();
s.close();
read.close();
write.close();
}
}
Your client is calling readLine() until it returns null, but your server is reading from the connection so it hasn't closed it yet, so the null will never arrive, so you're deadlocked.
Read one line from the server and then send a response, then close the socket. Have the server close the socket after it calls readLine().
I am trying to launch server and client thread on the same process, but seems like the server thread is blocking the client thread (or vice versa). I'm not allowed to use any global variable between those threads(like semaphore or mutex, since the client and the server thread are launched by upper-class that I don't have the access of).
I found a similar question here , but it still use two different process (two main function).
Here is a sample of my code
The server code:
public class MyServer implements Runnable{
ServerSocket server;
Socket client;
PrintWriter out;
BufferedReader in;
public MyServer() throws IOException{
server = new ServerSocket(15243, 0, InetAddress.getByName("localhost"));
}
#Override
public void run() {
while(true){
try {
ArrayList<String> toSend = new ArrayList<String>();
System.out.println("I'll wait for the client");
client = server.accept();
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inputLine;
while((inputLine = in.readLine()) != null){
toSend.add("answering : "+inputLine);
}
for(String resp : toSend){
out.println(resp);
}
client.close();
out.close();
in.close();
} catch (IOException ex) {
}
}
}
}
And the client code:
public class MyClient implements Runnable{
Socket socket;
PrintWriter out;
BufferedReader in;
public MyClient(){
}
#Override
public void run() {
int nbrTry = 0;
while(true){
try {
System.out.println("try number "+nbrTry);
socket = new Socket(InetAddress.getByName("localhost"), 15243);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("Hello "+nbrTry+" !! ");
String inputLine;
while((inputLine = in.readLine()) != null){
System.out.println(inputLine);
}
nbrTry++;
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
}
}
}
And the supposed upper-class launching those thread:
public class TestIt {
public static void main(String[] argv) throws IOException{
MyServer server = new MyServer();
MyClient client = new MyClient();
(new Thread(server)).start();
(new Thread(client)).start();
}
}
It gives me as output:
I'll wait for the client
Try number 0
And it stuck here. What should I do to keep both server and client code running?
Thank you.
I'll be willing to take up your questions but basically you need to think through your logic a bit more carefully.
MyServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer implements Runnable {
ServerSocket server;
public MyServer() throws IOException {
server = new ServerSocket(15243, 0, InetAddress.getByName("localhost"));
}
#Override
public void run() {
while (true) {
try {
// Get a client.
Socket client = server.accept();
// Write to client to tell him you are waiting.
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
out.println("[Server] I'll wait for the client");
// Let user know something is happening.
System.out.println("[Server] I'll wait for the client");
// Read from client.
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inputLine = in.readLine();
// Write answer back to client.
out.println("[Server] Answering : " + inputLine);
// Let user know what it sent to client.
System.out.println("[Server] Answering : " + inputLine);
in.close();
out.close();
client.close();
} catch (Exception e) {
}
}
}
}
MyClient.java
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;
public class MyClient implements Runnable {
Socket socket;
PrintWriter out;
BufferedReader in;
public MyClient() throws UnknownHostException, IOException {
}
#Override
public void run() {
int nbrTry = 0;
while (true) {
try {
// Get a socket
socket = new Socket(InetAddress.getByName("localhost"), 15243);
// Wait till you can read from socket.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String inputLine = in.readLine();
//inputLine contains the text '[Server] I'll wait for the client'. means that server is waiting for us and we should respond.
// Write to socket
out = new PrintWriter(socket.getOutputStream(), true);
out.println("[Client] Hello " + nbrTry + " !! ");
// Let user know you wrote to socket
System.out.println("[Client] Hello " + nbrTry++ + " !! ");
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
}
}
}
TestIt.java
import java.io.IOException;
public class TestIt {
public static void main(String[] argv) throws IOException {
MyServer server = new MyServer();
MyClient client = new MyClient();
(new Thread(server)).start();
(new Thread(client)).start();
}
}
Your client sends a string, then reads until the stream is exhausted:
while((inputLine = in.readLine()) != null){
BufferedReader.readLine() only returns null at the end of the stream, as I recall. On a stream, it will block until input is available
Your server receives until the stream is exhausted, then sends back its response.
After sending one line, you now have:
Your client waiting for a response.
Your server still waiting for more data from the client. But it doesn't send anything back until the end of the stream from the client (which never happens because the client is waiting for your response).
I made a simple chat server and client and the client will send text to the server, and the server will only send it back to the client that sent it to it. I want it to send to all the clients instead of just that one.
Server:
import java.io.IOException;
import java.net.ServerSocket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket s = null;
boolean listening = true;
try {
s = new ServerSocket(5555);
} catch (IOException e) {
e.printStackTrace();
}
while(listening)
new ServerThread(s.accept()).start();
}
}
Thread:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket sock = null;
public ServerThread(Socket socket) {
super("Server Thread.");
this.sock = socket;
}
public void run() {
PrintWriter out = null;
BufferedReader in = null;
try {
System.out.println(sock.getInetAddress() + " has joined.");
out = new PrintWriter(sock.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String input;
while((input = in.readLine()) != null) {
System.out.println(input);
out.println(input);
}
in.close();
out.close();
sock.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client
{
public static void main(String[] args) throws IOException {
Socket sock = null;
PrintWriter out = null;
BufferedReader in = null;
try {
sock = new Socket("127.0.0.1", 5555);
out = new PrintWriter(sock.getOutputStream(), true);
in = new BufferedReader(
new InputStreamReader(sock.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(
System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println(in.readLine());
}
out.close();
in.close();
sock.close();
}
}
Have your server keep List<ServerThread>. Have a void sendAll(String) method on the Server that can be accessed by the ServerThreads and when they get information, that sendAll() method tells each ServerThread to send out their information.
What you're looking at doing though will require some asynchronous work (and is most certainly not trivial!)
Well, briefly: you're creating those ServerThreads and starting them, but you're not keeping track of them in any way. Imagine if each time you created one, you put it in a HashSet. Then each time a client sent a String, you iterated over the Set and sent the String to each of the clients. A method sendMessage(String) in ServerThread would make this easier, of course.
Change your client to have one thread for reading from the server plus one thread for reading from the keyboard.
Create a function which allows server socket threads to communicate with each other and use synchronization so that only one thread is writing to each outputstream at one time. So in brief, create a list of server threads which is shared by all threads and move your PrintWriter into a field with a getter, so it can be accessed from outside.
glowcoder and Ernest Friedman-Hill seem to be giving good advice, but I wanted to add one thing: have you considered using the Observer pattern and java's default implementation of Observable?
The Server could extend the Observable object, and the ServerThread could implement the Observer interface. As you create new ServerThreads, register them with the Observable using
server.addObserver(serverThread);
The ServerThread will need to know about the Server it is linked to.
Then whenever a client sends in a new message, instead of out.println(userInput) do the following:
synchronized (server) {
server.setChanged();
server.notifyObservers(userInput);
}
You also need to implement ServerThread.update(Observable o, Object update), in which you would get the serverThread's socket's output stream and write ((String) update) to it.
Note that this will use one thread to send messages to all the observers and will block other threads from processing their chats until it has sent to all observers.