Server send message to all connected clients - java

I know this question has been asked before, and I've tried the different solutions, but I got stuck in the implementation part.. :(
Currently multiple clients can connect to the server, I used the multithreaded KnockKnock server/client example from javadocs, and edited it slightly so that you can just send messages to the server, and it will echo them back to you, but I want to be able to make it so that if client 1 sends a message, then the server will broadcast them back to all the clients connected to the server.
I've tried looking around and saw people in the same position as I am in now, and they were told to make a list to keep track of all the connections, and then iterate through the list and send the message, but I really don't know in which class to put it or how to handle it.
If someone could show me or just give me hints to where I should start, it would be greatly appreciated, as I'm really just stuck at the moment :(
Here's where I'm at so far:
Server:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
public static void main(String[] args) throws IOException {
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(4444)) {
while (listening) {
ServerThread thread = new ServerThread(serverSocket.accept());
thread.start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " );
System.exit(-1);
}
}
}
ServerThread
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ServerThread extends Thread{
private Socket socket = null;
public ServerThread(Socket socket) {
super("MultiServerThread");
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
while (true) {
String input = in.readLine();
System.out.println(input);
out.println("ecco " + input);
if (input.equals("Bye"))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client (not sure if necessary, but here is it anyways)
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 {
try (
Socket kkSocket = new Socket("172.30.242.51", 4444);
PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(kkSocket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
while (true) {
if(in != null) {
String input = stdIn.readLine();
out.println("Client: " + input);
System.out.println(in.readLine());
out.flush();
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " );
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " );
System.exit(1);
}
}
}
Have a nice weekend =)

Operation 'write' is blocking in your example. So iterating by all connections can lead to delays and blocking your push thread. Also always set SO_TIMEOUT for socket if you do not want to have memory leaks.
I suggest using netty server
It has very nice functionality for pushing data to all connected clients - look for ChannelGroup

Why don't you use NIO to solve this problem?
A simple example:
public class EchoServer {
public static void main(String[] args) throws Exception {
//Create TCP server channel
ServerSocketChannel serv = ServerSocketChannel.open();
ServerSocket sock = serv.socket();
//Create a socket on your IP and port (i.e: localhost:12345)
SocketAddress addr = new InetSocketAddress(12345);
//Bind server socket and socket address
sock.bind(addr);
//Configure socket so all its methods won't be blocking
serv.configureBlocking(false);
//Create a selector to attend all the incoming requests
Selector selector = Selector.open();
//Register into the selector the accept request type
serv.register(selector,SelectionKey.OP_ACCEPT);
//Create a common buffer
ByteBuffer commonBuffer = ByteBuffer.allocate(10000);
commonBuffer.clear();
Iterator<SelectionKey> it = null;
ByteBuffer channelBuffer = null;
for (;;){ //Infinite loop
System.out.println("Waiting for events......");
selector.select(); // This call do is blocking
System.out.println("New event received");
it = selector.selectedKeys().iterator();
while(it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
System.out.println(String.format("Processing %s", key));
it.remove(); // Remove it to avoid duplications
try{
if (key.isAcceptable()) {
System.out.println("Received new connection request");
processConnectionRequest(serv, selector);
}else if (key.isReadable()) {
System.out.println("Received new reading request");
processReadingRequest(selector, commonBuffer, key);
}else if (key.isWritable()) {
System.out.println("Received new writing request");
processWritingRequest(key);
}
}catch(Exception e){
key.cancel();
try {
key.channel().close();
} catch (Exception ce) {}
}//end catch
}//end while
}//end for
}//end main
private static void processWritingRequest(SelectionKey key) throws IOException {
SocketChannel cli = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
System.out.println(String.format("Wrinting into the channel %s", cli));
buf.flip();//prepare the buffer
buf.rewind();
cli.write(buf);
if (buf.hasRemaining()) {
//If there is more content remaining, compact the buffer
buf.compact();
} else {
buf.clear();
key.interestOps(SelectionKey.OP_READ);
}
}
private static void processReadingRequest(Selector selector, ByteBuffer commonBuffer, SelectionKey key)
throws IOException {
SocketChannel cli = (SocketChannel) key.channel();
if (cli.read(commonBuffer) == -1) {
System.out.println(String.format("Closing channel %s", cli));
cli.close(); // internally calls key.cancel()
}
else {//Send the data to all the channels
commonBuffer.flip();//prepare the buffer
Iterator<SelectionKey> it2 = selector.keys().iterator();
System.out.println("Writing data to all the channels");
SelectionKey keys = null;
while(it2.hasNext()) {
keys = it2.next();
System.out.println(String.format("Writing in %s", keys));
ByteBuffer buf = (ByteBuffer) keys.attachment();
if(buf!=null)
{
buf.put(commonBuffer);
keys.interestOps(SelectionKey.OP_WRITE|SelectionKey.OP_READ);
commonBuffer.rewind();
}
}
commonBuffer.clear();
}
}
private static void processConnectionRequest(ServerSocketChannel serv, Selector selector)
throws IOException, ClosedChannelException {
ByteBuffer channelBuffer;
SocketChannel cli = serv.accept();
cli.configureBlocking(false);
channelBuffer = ByteBuffer.allocate(10000);
System.out.println(String.format("Registering new reading channel: %s", cli));
cli.register(selector, SelectionKey.OP_READ, channelBuffer);
}
}

Related

Transferring files through Java NIO APIs

I'm trying to transfer an mp3 file from Server to Client using Java NIO APIs.
In particular, I am trying to use transferTo & transferFrom methods.
I've already checked that the server recognizes the file appropriately and transfers to a FileChannel.
However, in the point of view of the client, it considers that the size of the FileChannel connected to the server is 0 which can be interpreted that the client did not receive any files from the channel.
Here are the results on the consoles of both server and client.
[Server]
Server is started...
java.nio.channels.SocketChannel[connected local=/127.0.0.1:7777 remote=/127.0.0.1:60430]Here comes a new client!
!!write activated!!
Channel size : 3622994
filename : C:\Users\InhoKim\Music\5 O'clock - Black Nut.mp3
java.nio.channels.SocketChannel[connected local=/127.0.0.1:7777 remote=/127.0.0.1:60430]The number of files transferred : 1
[Client]
!!read activated!!
Channel size : 0
How do I have to solve this problem?
Here are the full codes of both server and client
[Server]
import java.io.File;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.net.ServerSocket;
import java.net.InetSocketAddress;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.FileChannel;
import java.io.FileInputStream;
import java.util.Set;
import java.nio.ByteBuffer;
public class MusicServer {
private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;
private ServerSocket serverSocket = null;
File dir = new File("C:\\Users\\InhoKim\\Music\\");
boolean test = true;
public static void main(String[] args) {
MusicServer ms = new MusicServer();
ms.initServer();
ms.startServer();
}
public void initServer() {
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocket = serverSocketChannel.socket();
InetSocketAddress isa = new InetSocketAddress("localhost", 7777);
serverSocket.bind(isa);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch(Exception e) {e.printStackTrace();}
}
public void startServer() {
System.out.println("Server is started...");
try {
while (true) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
SelectableChannel channel = key.channel();
if (channel instanceof ServerSocketChannel) {
if (key.isAcceptable())
accept(key);
} else {
if (key.isWritable()) {
if(test)
write(key);
}
}
}
}
} catch(Exception e) {e.printStackTrace();}
}
private void accept(SelectionKey key) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
try {
SocketChannel sc = server.accept();
if (sc == null) return;
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_WRITE);
System.out.println(sc.toString() + "Here comes a new client!");
} catch(Exception e) {e.printStackTrace();}
}
private void write(SelectionKey key) {
if(test)
System.out.println("!!write activated!!");
test = false;
SocketChannel sc = (SocketChannel) key.channel();
try {
File[] files = dir.listFiles();
int count = 0;
for (File file : files) {
count++;
FileInputStream fis = new FileInputStream(file);
FileChannel inChannel = fis.getChannel();
System.out.println("Channel size : " + (int)inChannel.size());
System.out.println("filename : " + file);
inChannel.transferTo(0, (int)inChannel.size(), sc);
fis.close();
break;
}
System.out.println(sc.toString() + "The number of files transferred : " + count);
} catch(Exception e) {e.printStackTrace();}
}
}
[Client]
import java.io.File;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.SelectionKey;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.util.Set;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
public class MusicClient {
private Selector selector = null;
private SocketChannel sc = null;
int count = 0;
public static void main(String[] args) {
MusicClient mc = new MusicClient();
mc.startServer();
}
public void initServer() {
try {
selector = Selector.open();
sc = SocketChannel.open(new InetSocketAddress("127.0.0.1", 7777));
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
} catch(Exception e) {e.printStackTrace();}
}
public void startServer() {
initServer();
startReader();
}
public void startReader() {
try {
while (true) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if (key.isReadable()) {
read(key);
System.exit(0);
}
}
}
} catch(Exception e) {e.printStackTrace();}
}
private void read(SelectionKey key) {
System.out.println("!!read activated!!");
SocketChannel sc = (SocketChannel) key.channel();
try {
File dir = new File("D:\\Target2\\");
FileOutputStream fos = new FileOutputStream(dir + "\\" + count + ".mp3"); // file name has been set as a number
count++;
FileChannel outChannel = fos.getChannel();
System.out.println("Channel size : " + (int)outChannel.size());
outChannel.transferFrom(sc, 0, (int)outChannel.size());
fos.close();
} catch(Exception e) {e.printStackTrace();}
}
}
in the point of view of the client, it considers that the size of the FileChannel connected to the server is 0
There is no such thing as a 'FileChannel connected to the server'. File channels are connected to files. What you have is a FileChannel connected to a new FileOutputStream which has just created a new file, whose size is therefore zero.
which can be interpreted that the client did not receive any files from the channel.
No, it can be interpreted as you telling the FileChannel to transfer zero bytes, which it did correctly.
You can't get the size of a SocketChannel, because it doesn't mean anything (consider a peer that just keeps sending and never closes the connection). So in this case you have to use Long.MAX_VALUE as the size. The transfer will complete when there are no more bytes to be transferred, or indeed before, especially as you are using non-blocking mode.
EDIT I don't see any reason to use non-blocking mode in the client. I would remove that, and the Selector. And transferFrom() must be called in a loop that terminates when it returns zero. Using transferTo() in the server is considerably more complex if you must use non-blocking mode there, as you have to register OP_WRITE when it returns zero and re-select and restart using an adjusted offset when you get it, and deregister OP_WRITE if it doesn't return zero.

Exampels on a Server-Client-Chat applikation on JAVA [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 8 years ago.
Improve this question
I have been "googeling" around for a long time for examples over Server-client-chat application, but I can't really understand them. Many of them are using a class and creates the GUI from it, and I don't want to copy straight from it. Alot of examples doesn't either really explain how you send messages from a client to the server and then it sends the message out to all the other clients.
I am using NetBeans and I was wondering if there is some good tutourials or examples that can help me with this?
Here comes the multiThreading program :) the server has two classes, and client has one. Hope you Like it!
SERVER MAIN CLASS:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static void main(String[] args) throws IOException {
int MAXCLIENTS = 20;
int port = 4444;
ServerSocket server = null;
Socket clientSocket = null;
// An array of clientsConnected instances
ClientThread[] clientsConnected = new ClientThread[MAXCLIENTS];
try {
server = new ServerSocket(port);
System.out.println("listening on port: " + port);
} catch (IOException e) {// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
try {
clientSocket = server.accept();
} catch (IOException e) {
e.printStackTrace();
if (!server.isClosed()){server.close();}
if (!clientSocket.isClosed()){clientSocket.close();}
}
System.out.println("Client connected!");
for (int c = 0; c < clientsConnected.length; c++){
if (clientsConnected[c] == null){
// if it is empty ( null) then start a new Thread, and pass the socket and the object of itself as parameter
(clientsConnected[c] = new ClientThread(clientSocket, clientsConnected)).start();
break; // have to break, else it will start 20 threads when the first client connects :P
}
}
}
}
}
SERVER CLIENT CLASS:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class ClientThread extends Thread{
private ClientThread[] clientsConnected;
private Socket socket = null;
private DataInputStream in = null;
private DataOutputStream out = null;
private String clientName = null;
//Constructor
public ClientThread(Socket socket, ClientThread[] clientsConnected){
this.socket = socket;
this.clientsConnected = clientsConnected;
}
public void run(){
try {
// Streams :)
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
String message = null;
clientName = in.readUTF();
while (true){
message = in.readUTF();
for (int c = 0; c < clientsConnected.length; c++){
if (clientsConnected[c]!= null && clientsConnected[c].clientName != this.clientName){ //dont send message to your self ;)
clientsConnected[c].sendMessage(message, clientName); // loops through all the list and calls the objects sendMessage method.
}
}
}
} catch (IOException e) {
System.out.println("Client disconnected!");
this.clientsConnected = null;
}
}
// Every instance of this class ( the client ) will have this method.
private void sendMessage(String mess, String name){
try {
out.writeUTF(name + " says: " + mess);
} catch (IOException e) {
e.printStackTrace();
}
}
}
AND FINALLY THE CLIENT:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) throws IOException {
Main m = new Main();
m.connect();
}
public void connect() throws IOException{
//declare a scanner so we can write a message
Scanner keyboard = new Scanner(System.in);
// localhost ip
String ip = "127.0.0.1";
int port = 4444;
Socket socket = null;
System.out.print("Enter your name: ");
String name = keyboard.nextLine();
try {
//connect
socket = new Socket(ip, port);
//initialize streams
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
//start a thread which will start listening for messages
new ReceiveMessage(in).start();
// send the name to the server!
out.writeUTF(name);
while (true){
//Write messages :)
String message = keyboard.nextLine();
out.writeUTF(message);
}
}
catch (IOException e){
e.printStackTrace();
if (!socket.isClosed()){socket.close();}
}
}
class ReceiveMessage extends Thread{
DataInputStream in;
ReceiveMessage(DataInputStream in){
this.in = in;
}
public void run(){
String message;
while (true){
try {
message = in.readUTF();
System.out.println(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
I ran the server in eclipse, and started two clients from the CMD, looks like this:
Here is a super simple I made just now with some comments of what is going on. The client connects to the server can can type messages which the server will print out. This is not a chat program since the server receives messages, and the client send them. But hopefully you will understand better it better :)
Server:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static DataInputStream in;
public static DataOutputStream out;
public static void main(String[] args) throws IOException {
int port = 4444;
ServerSocket server = null;
Socket clientSocket = null;
try {
//start listening on port
server = new ServerSocket(port);
System.out.println("Listening on port: " + port);
//Accept client
clientSocket = server.accept();
System.out.println("client Connected!");
//initialize streams so we can send message
in = new DataInputStream(clientSocket.getInputStream());
out = new DataOutputStream(clientSocket.getOutputStream());
String message = null;
while (true) {
// as soon as a message is being received, print it out!
message = in.readUTF();
System.out.println(message);
}
}
catch (IOException e){
e.printStackTrace();
if (!server.isClosed()){server.close();}
if (!clientSocket.isClosed()){clientSocket.close();}
}
}
}
Client:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) throws IOException {
//declare a scanner so we can write a message
Scanner keyboard = new Scanner(System.in);
// localhost ip
String ip = "127.0.0.1";
int port = 4444;
Socket socket = null;
try {
//connect
socket = new Socket(ip, port);
//initialize streams
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
while (true){
System.out.print("\nMessage to server: ");
//Write a message :)
String message = keyboard.nextLine();
//Send it to the server which will just print it out
out.writeUTF(message);
}
}
catch (IOException e){
e.printStackTrace();
if (!socket.isClosed()){socket.close();}
}
}
}

Java Socket Server won't process second client

I've got a client and server coded in Java, once the server has received one message from the client, the server stops receiving all new messages. No errors are thrown when the client tries to sent more messages. I can't seem to find out why it doesn't allow or receive new connections! Please help.
public class Server implements Runnable {
#Override
public void run() {
ServerSocket echoServer = null;
String line;
DataInputStream is;
PrintStream os;
Socket clientSocket = null;
boolean Listening = true;
int sPort = 9999;
// Try to open a server socket on port 9999
try {
echoServer = new ServerSocket(sPort);
}
catch (IOException e) {
System.out.println(e);
}
// Create a socket object from the ServerSocket to listen and accept
// connections.
// Open input and output streams
while (Listening){
try {
clientSocket = echoServer.accept();
is = new DataInputStream(clientSocket.getInputStream());
//os = new PrintStream(clientSocket.getOutputStream());
// As long as we receive data, echo that data back to the client.
while (true) {
line = is.readLine();
if(line != null){
//os.println(line);
log(Level.SEVERE, "New connection to server {0}", line);
}
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
while (true)
{
line = is.readLine();
if(line != null){
//os.println(line);
log(Level.SEVERE, "New connection to server {0}", line);
}
}
after accepting a connection it is entering into this infinite loop.due to this loop it will never accept new connection.
to solve this issues, start new thread each time when new client comes, pass socket connection of the client and read data from that client.
I see two issues as below:
while (true) {
line = is.readLine();
if(line != null){
//os.println(line);
log(Level.SEVERE, "New connection to server {0}", line);
}
Here you need to break after reading the content from the Socket irrespective of whether you read in different thread or same.
You need to declare boolean Listening to volatile else the server wont stop.
while (true) {
line = is.readLine();
if(line != null){
//os.println(line);
log(Level.SEVERE, "New connection to server {0}", line);
}
}
the code will block new request, so the second request will not be accepted.
I make an example accounding to your code. Hope it help to you.
The Server Class will only be userd to accept socket connection and create a new thread to process it.
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server implements Runnable {
#Override
public void run() {
ServerSocket echoServer = null;
boolean listening = true;
Socket clientSocket = null;
int sPort = 9999;
// Try to open a server socket on port 9999
try {
echoServer = new ServerSocket(sPort);
} catch (IOException e) {
System.out.println(e);
}
// Create a socket object from the ServerSocket to listen and accept
// connections.
// Open input and output streams
while (listening) {
try {
clientSocket = echoServer.accept();
System.out.println("receive new connection");
new ProcessClientThread(clientSocket).start();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
}
The ProcessClientThread Class extends Thread Class and defined a constructor with a Socket type parameter. Override run method of it. The run method get input stream from socket and print it out. When it accept 0, it will close the scoket connection. Its code like this
import java.io.DataInputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
public class ProcessClientThread extends Thread {
Socket socket = null;
public ProcessClientThread(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
DataInputStream is;
String line;
boolean flag = true;
try {
is = new DataInputStream(socket.getInputStream());
while (flag) {
line = is.readLine();
if (Integer.valueOf(line) != 0) {
// os.println(line);
// Logger.getLogger(Level.SEVERE,
// "New connection to server {0}", line);
System.out.println(line);
} else {
Writer w = new OutputStreamWriter(socket.getOutputStream());
w.write(0);
w.flush();
flag = false;
socket.close();
System.out.println("close a connection");
}
}
} catch(Exception e) {
}
}
}
There is a StartUp Class which used to start up the server thread.
public class StartUp {
public static void main(String[] args) {
new Thread(new Server()).start();
}
}
Run the below Client Class to test the Server.
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
Socket client = new Socket("localhost", 9999);
OutputStreamWriter writer = new OutputStreamWriter(client.getOutputStream());
Reader reader = new InputStreamReader(System.in);
Reader serverReader = new InputStreamReader(client.getInputStream());
boolean flag = true;
while(flag) {
int readContent = reader.read();
writer.write(readContent);
writer.flush();
if(readContent == 0) {
writer.close();
client.close();
flag = false;
}
}
}
}

Socket in multithreading "deadlocked" Java

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).

ask about deliver message between client to client

hi i writ acode for client and for server and now i want to deliver the message between clint one to clint two and i dont succees to do this on server side i want to construct array for name and id and after i send message from the client side i can choose where or Which name the server deliver the message pleas help me to writ this
so this is the clint side
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class client {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader readerFromCommandLine = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
System.out.println("Say something:");
String userInput = readerFromCommandLine.readLine();
writer.println(userInput);
writer.flush();
String input = reader.readLine();
System.out.println("Got from server: "+input);
if (userInput.equalsIgnoreCase("bye")) {
break;
}
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
so now my code shuold by look like this ?
becaus i not yet can send from one client to client two
import java.awt.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class server {
public static void main(String[] args) {
ArrayList<Channel> my_clients = new ArrayList<Channel>();
ServerSocket ss = null;
try {
ss = new ServerSocket(7777);
while (true) {
//wait for a new client call - once got it, get the socket for
//that channel
System.out.println("Waiting for an incoming call");
Socket client = ss.accept();
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
//once the call has started read the client data
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
//my_client.writer("HELLO!");
}
}
//System.out.println("Accepted a new call");
//new Channel(client).start();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (ss != null) {
try {
ss.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
public static class Channel extends Thread {
private static int clientIndex = 0;
private int index;
private Socket socket = null;
public Channel(Socket socket) {
clientIndex++;
index = clientIndex;
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true) {
String input = reader.readLine();
System.out.println("Got from client "+index+": "+input);
//bye bye
if (input.equalsIgnoreCase("bye")) {
break;
}
writer.println("Gotcha");
writer.flush();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
}
String userInput = readerFromCommandLine.readLine();
BufferedReader.readLine() is a problem here. It is going to block your thread until input is received. This means communication can only ever go in one direction at a time, and can potentially get totally blocked if both clients are waiting.
DataFetcher can fix this problem; you can use it to listen in a separate Thread
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/
You half way there.
You created a Threaded Server were each connection from a client opens a thread. This thread then loops and waits for messages.
Think of these threads as you connected clients with their own objects / properties and their streams to write to and read from them.
So each time a clients connections you want to create their thread add it to some kind of list and start their thread. For example:
At the top of the class
List<Channel> my_clients = new List<Channel>();
In your while loop
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
Then when you want to send a message to a certain clients. You can loop all the Threads and look for one that has some kind of name or Unique Indentifier. For example:
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
my_client.write("HELLO!");
}
}
or in the same breath you could send a message to all your clients (Broadcast):
for(Channel my_client : my_clients) {
my_client.write("HELLO!");
}
remember to remove the clients when they disconnect too!
// Can't remember the precise exception correct my if I'm wrong!
catch(SocketException ex) {
my_clients.remove(this);
}
Note this expects that you some how authenticate and know the name of your client or supply them a UID which you reference when you are instructed to sent them something. And that the Channel class has the Write Method for connivance.
Hope that Help!

Categories

Resources