I do not know Netty, but from the link you've been through, I believe he's sending the messages to everyone in this method:
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
// Send the received message to all channels but the current one.
for (Channel c: channels) {
if (c != ctx.channel()) {
c.writeAndFlush("[" + ctx.channel().remoteAddress() + "] " + msg + '\n');
} else {
c.writeAndFlush("[you] " + msg + '\n');
}
}
}
And, apparently, every Channel
represents a user connected to the server. If you choose only one of them, only that client will receive the message.
In any case, I believe Netty offers a number of features that you should not need at the moment. I'd start by taking a look at the java docs tutorials . There is a ready example of server and client .
Although they are very simple, with some modifications, it is possible to transform them into a complete chat program, with separate messages for each user.
Here is my experience, based on the javadocs tutorial.
I've included ArrayList<>
to save connecting users:
public static ArrayList<SCThread> lista = new ArrayList<SCThread>();
And when the server receives a message, I loop like Netty's, but this time looking for the recipient of the message.
Server example:
Exampleclients(inmyversion,x<msg>
sendsmessagetoeveryone):
Already<número><msg>
sendsthemessagetotheuserwiththisnumber:
ServerChat.java:
importjava.net.*;importjava.io.*;publicclassServidorChat{publicstaticvoidmain(String[]args)throwsIOException{if(args.length!=1){System.err.println("Utilizacao: java ServidorChat <porta>");
System.exit(1);
}
System.out.println("ServidorChat");
int porta = Integer.parseInt(args[0]);
boolean portaAberta = true;
try (ServerSocket servidorSocket = new ServerSocket(porta)) {
while (portaAberta) {
SCThread s = new SCThread(servidorSocket.accept());
s.start();
Usuarios.adicionar(s);
}
} catch (IOException e) {
System.err.println("Erro ao abrir a porta " + porta);
System.exit(-1);
}
}
}
SCThread.java:
import java.net.*;
import java.io.*;
public class SCThread extends Thread {
private Socket socket = null;
public SCThread(Socket socket) {
super("ServidorChatThread");
this.socket = socket;
}
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
for (int i = 0; i < Usuarios.lista.size(); i++) {
if (inputLine.startsWith(i + " ")) {
Usuarios.lista.get(i).envia(this.getName() + " te diz: " + inputLine.substring(2));
}
}
if (inputLine.startsWith("x ")) {
for (SCThread usuario : Usuarios.lista) {
if (usuario != this) {
usuario.envia(this.getName() + ": " + inputLine.substring(2));
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void envia(String msg) throws IOException {
socket.getOutputStream().write((msg + "\n").getBytes());
}
}
ChatClient.java
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatCliente {
static Socket s;
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.err.println("Utilizacao: java ChatCliente <endereco> <porta>");
System.exit(1);
}
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);
s = new Socket(hostName, portNumber);
ClienteThread cT = new ClienteThread(s);
cT.start();
Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
enviar(scan.nextLine() + "\n");
}
scan.close();
}
public static void enviar(String str) throws IOException {
s.getOutputStream().write(str.getBytes());
}
}
ClientThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClienteThread extends Thread {
BufferedReader in;
public ClienteThread(Socket s) throws IOException {
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
String mensagem;
public void run() {
try {
while ((mensagem = in.readLine()) != null)
System.out.println(mensagem);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Users.java
import java.io.IOException;
import java.util.ArrayList;
public class Usuarios {
public static ArrayList<SCThread> lista = new ArrayList<SCThread>();
public static void adicionar(SCThread u) throws IOException {
lista.add(u);
u.setName("Usuario " + (lista.size() - 1));
u.envia("Servidor: Voce eh o " + u.getName());
System.out.println("Quantidade de usuarios: " + lista.size());
}
}
Note that this is just a general idea. Many steps have been put aside, and many things need to be implemented. For example:
This code is not thread safe (if many users connect at the same time, it will hang). Most notable is ArrayList<>
that should be replaced, as said here .
There is no such thing as connection breakdown - if a user disconnects, it will start to give error as well (I've removed it to reduce the size of the code).