Trying to build a simple multi-threaded chat server that runs via command prompt. The clients do connect to the server and the server will hold multiple clients, however when trying to send messages from one client to the other, or even notifying a client of another user logging in, nothing comes up on the client command prompt.
public class Server {
private static ServerSocket servSock;
private static Socket clientSock;
private static ArrayList<ClientThread> clientList;
private static int IDcount = 0;
public static void main(String args[]){
// Get command line arguments.
if (args.length != 3) {
System.out.println("Required arguments: server port, block duration, timeout");
return;
}
int port = Integer.parseInt(args[0]);
int blockDur = Integer.parseInt(args[1]);
int timeout = Integer.parseInt(args[2]);
try{
servSock = new ServerSocket(port);
clientList = new ArrayList<ClientThread>();
}
catch(IOException ex){
System.err.println(ex);
}
while (true) {
try {
clientSock = servSock.accept();
ClientThread thread = new ClientThread(clientSock);
clientList.add(thread);
thread.start();
} catch (IOException e) {
System.out.println(e);
}
}
}
private synchronized static void broadcast(String msg){
System.out.print(msg);
for(int i = 0; i < clientList.size(); i++){
ClientThread client = clientList.get(i);
client.send(msg);
}
}
synchronized static void unlist(int id){
for(int i = 0; i < clientList.size(); i++){
ClientThread thread = clientList.get(i);
if(thread.id == id){
clientList.remove(i);
return;
}
}
}
static class ClientThread extends Thread {
Socket sock;
BufferedReader tIn;
PrintWriter tOut;
int id;
String username;
String msg;
ClientThread(Socket sock){
id = IDcount++;
this.sock = sock;
try{
tIn = new BufferedReader(new InputStreamReader(sock.getInputStream()));
tOut = new PrintWriter(sock.getOutputStream());
username = tIn.readLine();
broadcast(username + " logged in");
}
catch(IOException ex){
System.err.println(ex);
}
}
public void run(){
boolean loggedIn = true;
while(loggedIn){
try{
msg = tIn.readLine();
}
catch (IOException ex){
System.err.println(ex);
}
String[] parts = msg.split("\\s",2);
String type = parts[0];
Client code is similar
public class Client{
private static Socket clientSock;
private static BufferedReader in;
private static PrintWriter out;
private static Scanner scan;
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out.println("Required arguments: server IP, server port");
return;
}
String host = args[0];
int port = Integer.parseInt(args[1]);
clientSock = new Socket(host, port);
in = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
out = new PrintWriter(clientSock.getOutputStream());
scan = new Scanner(System.in);
new ListenFromServer().start();
boolean online = true;
System.out.println("Enter your username:");
String username = scan.nextLine();
out.println(username);
while(online){
System.out.println("> ");
String msg = scan.nextLine();
String[] parts = msg.split("\\s");
String type = parts[0];
send(msg);
if(type.equalsIgnoreCase("logout")){
online = false;
}
}
logoff();
}
static void send(String msg) throws IOException{
out.println(msg);
}
private static void logoff() throws IOException{
in.close();
out.close();
scan.close();
clientSock.close();
}
static class ListenFromServer extends Thread{
public void run(){
while(true){
try{
String msg = in.readLine();
System.out.println(msg);
}
catch(IOException ex){
System.err.println(ex);
}
}
}
}
}
When you send data with PrintWriter.println(), data write to buffer. You must call PrintWriter.flush() after println to send data to or from the server immediately.
And when you call username = tIn.readLine(); in ClientThread constructor, you block main-thread, because constructor calls in main-thread. So, while connected user won't send username, other clients can't connect.
I'm trying to learn how to use java sockets before next semester. I wrote this program that is supposed to accept accept a message from a sender and send the message to a reciever. You specify the reciever by writing the name of the client that is connected, if the client isn't connected then the server will respond by sending the message "DISCONNECTED". But for some reason the message isn't sent to the reciever. I can still send the message to the sender though. Is this the right forum to ask for this kind of help?
This is my client class
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class MyTestClient {
static int port = 0;
static String ip = "";
static String name = "";
public static void main(String args[] ) {
if(args.length == 3) {
try{
port = Integer.parseInt(args[1]);
} catch(NumberFormatException e) {
System.out.println("Usage: Java MyTestClient <ip> <port> <name>");
System.exit(0);
}
ip = args[0];
name = args[2];
} else {
System.out.println("Usage: Java MyTestClient <ip> <port> <name>");
System.exit(0);
}
try {
Socket socket = new Socket(ip, port);
new Thread(new MessageHandler(socket)).start();
new Thread(new InputHandler(socket)).start();
} catch (IOException e) {
System.out.println("Could not connect to: " + ip + " : " + port);
System.exit(0);
}
}
public static class MessageHandler implements Runnable {
Socket socket;
public MessageHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter out = null;
BufferedReader in = null;
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}catch(IOException e) {
e.printStackTrace();
}
String fromServer;
try {
while ((fromServer = in.readLine()) != null) {
System.out.println(fromServer);
fromServer.trim();
if(fromServer.contains(" ")) {
String split[] = fromServer.split(" ", 2);
System.out.println(split.length == 2 ? split[1] + " Is a two part message" : "Strange message");
} else {
if(fromServer.equals("NAME")) {
System.out.println("Server asks for name | gives given name to server");
out.println(name);
}
if(fromServer.equals("SUCCESS")) {
System.out.println("Message succesfully sent");
}
if(fromServer.equals("ERROR")) {
System.out.println("Something went wrong when sending the message");
}
if(fromServer.equals("OCCUPIED")) {
System.out.println("Name was already used. Start the program with another name");
socket.close();
System.exit(0);
}
if(fromServer.equals("DISCONNECTED")) {
System.out.println("The reciever was not connected");
}
if(fromServer.equals("REGISTERED")) {
System.out.println("Successfully logged in to server");
}
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
}
public static class InputHandler implements Runnable {
Socket socket;
public InputHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
String fromUser = null;
PrintWriter out = null;
try {
out = new PrintWriter(socket.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader kbi = new BufferedReader(new InputStreamReader(System.in));
try {
while ((fromUser = kbi.readLine()) != null) {
out.println(fromUser);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
This is my server class
import java.io.*;
import java.net.*;
import java.util.*;
public class MyServer {
public static int port;
public static int maxConnections;
public static final String NAME = "Server";
private static Map<String, Socket> socketsMap = new HashMap<>();
public static void main(String args[]) {
if(args.length == 2) {
try{
port = Integer.parseInt(args[0]);
maxConnections = Integer.parseInt(args[1]);
}catch(Exception e){
System.out.println("Usage: Java Myserver <port> <maxConnections>");
System.exit(0);
}
} else {
System.out.println("Usage: Java Myserver <port> <maxConnections>");
System.exit(0);
}
new Thread(new ConnectionHandler(port, maxConnections)).start();
}
public static class ConnectionHandler implements Runnable {
private ServerSocket server;
private Socket socket = null;
public int currentSocket = 0;
public int port = 0;
public int maxConnections = 0;
public ConnectionHandler(int port, int maxConnections) {
this.maxConnections = maxConnections;
this.port = port;
}
#Override
public void run() {
try {
server = new ServerSocket(7777);
} catch (IOException e1) {
System.out.println("Server could not connect to port: " + port);
e1.printStackTrace();
System.exit(0);
}
while(currentSocket++ < maxConnections) {
try {
socket = server.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("NAME");
String message;
while((message = in.readLine()) != null) {
if(!socketsMap.containsKey(message) || message.equals("SERVER")) {
out.println("REGISTERED");
socketsMap.put(message, socket);
System.out.println(message + " has logged on server");
new Thread(new SocketHandler(socketsMap.get(message))).start();
} else {
out.println("OCCUPIED");
System.out.println(socket.getInetAddress().toString() + " has tried to login with existing name " + message);
socket.close();
currentSocket--;
}
socket = null;
break;
}
} catch (IOException e) {
System.out.println("Something went wrong with client connection");
}
}
}
}
public static class SocketHandler implements Runnable {
Socket socket = null;
public SocketHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter respond = new PrintWriter(socket.getOutputStream(), true);
String input;
while((input = in.readLine() ) != null) {
String[] info = input.split(" ", 2);
if(info.length != 2){
System.out.println("Message computed wrong");
respond.println("ERROR");
break;
}
if(info[0].equals("SERVER")) {
//TODO: Write a server command handler class
} else if ( socketsMap.containsKey(info[0]) ){
Socket reciever = socketsMap.get(info[0]);
PrintWriter out = new PrintWriter(reciever.getOutputStream());
respond.println("SUCCESS");
System.out.println(info[0] + " send the message: "+ info[1]);
out.println("MESSAGE" + " " + info[1]);
break;
} else {
System.out.println("Reciever is not connected");
respond.println("DISCONNECTED");
}
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
Maybe you can run it on your computers and see what i mean?
#Override
public void run() {
try {
server = new ServerSocket(7777);
} catch (IOException e1) {
System.out.println("Server could not connect to port: " + port);
e1.printStackTrace();
System.exit(0);
}
change the code above to
#Override
public void run() {
try {
server = new ServerSocket(port);
} catch (IOException e1) {
System.out.println("Server could not connect to port: " + port);
e1.printStackTrace();
System.exit(0);
}
I have been working on a message system where users type in a server IP/Port and that server then takes in messages and relays them to all other users on the server. The whole program was based of a echo server i rewrote from scratch, for every server.accept() socket it creates two Threads, one to receive messages and one to send them back. The two Threads are connected by a DatagramPacket system so if the server receives a message from one socket it sends it back to all other users because their Threads are listening for the same thing, this is where i am encountering problems; everything work fine except the fact that the user who receives the message alternates in order to time of log on.
Example of problem when two clients are connected:
Client #1 sends 10 messages:
0
1
2
3
4
5
6
7
8
9
The Server receives all of them.
Client #1 receives:
1
3
5
7
9
Client #2 receives:
0
2
4
6
8
Here is the code for the Client:
import java.io.*;
import java.util.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MessageClient {
public static void main(String[] args) {
System.out.println("Starting Message System...");
Scanner in = new Scanner(System.in);
MessageClient mc = new MessageClient();
String input;
System.out.println(":System Started, type help for help.");
System.out.print(":");
while (true) {
input = in.nextLine();
if (input.equalsIgnoreCase("HELP")) {
mc.printHelp();
System.out.print(":");
} else if (input.equalsIgnoreCase("QUIT")) {
System.exit(0);
} else if (input.equalsIgnoreCase("CONNECT")) {
mc.connect(in);
in.nextLine();
System.out.print(":");
} else {
System.out.print("No command found.\n:");
}
}
}
public static void printHelp() {
System.out.println("help\tShow this prompt\nconnect\tStarts a new connection\nquit\tQuit the program\nexit\tExit a connection");
}
public void connect(Scanner in) {
Socket soc = null;
InetAddress addr = null;
System.out.print("IP_ADDRESS/HOST:");
String ip = in.nextLine();
System.out.print("PORT:");
int port = in.nextInt();
try {
System.out.println("Attempting to connect to HOST:\'" + ip + "\' on PORT:\'" + port + "\'");
addr = InetAddress.getByName(ip);
soc = new Socket(addr, port);
} catch(Exception e) {
System.out.println("Error connecting to server: " + e.getLocalizedMessage());
return;
}
SwingUtilities.invokeLater(new MessageGUI(ip + ":" + port, soc));
}
}
class MessageGUI implements Runnable {
public MessageGUI(String windowName, Socket server) {
JFrame window = new JFrame(windowName);
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.setSize(500, 300);
window.setLayout(new BorderLayout());
window.setVisible(true);
MessageReceive mr = new MessageReceive(server);
mr.setEditable(false);
mr.setBackground(new Color(0, 0, 0));
mr.setForeground(new Color(0, 255, 0));
mr.setVisible(true);
new Thread(mr).start();
window.add(mr, BorderLayout.CENTER);
DataOutputStream dos = null;
try {
dos = new DataOutputStream(server.getOutputStream());
} catch(Exception e) {
System.out.println("Error creating output stream to server: " + e.getLocalizedMessage());
}
JTextField input = new JTextField();
input.addActionListener(new MessageSend(server, input, dos));
input.setBackground(new Color(0, 0, 0));
input.setForeground(new Color(0, 255, 0));
window.add(input, BorderLayout.PAGE_END);
System.out.println("Displaying connection.");
}
public void run() {}
}
class MessageReceive extends JTextArea implements Runnable {
protected Socket server;
public MessageReceive(Socket server) {
this.server = server;
}
public void run() {
DataInputStream dis = null;
int bytes;
try {
dis = new DataInputStream(server.getInputStream());
} catch(Exception e) {
System.out.println("Error connecting server: " + e.getLocalizedMessage());
}
this.append("Connected.\n");
while (true) {
try {
while ((bytes = dis.read()) != -1) this.append(String.valueOf((char) bytes));
} catch(Exception e) {
System.out.println("Error reading from server: " + e.getLocalizedMessage());
return;
}
}
}
}
class MessageSend implements ActionListener {
protected Socket server;
protected JTextField input;
protected DataOutputStream dos = null;
public MessageSend(Socket server, JTextField input, DataOutputStream dos) {
this.server = server;
this.input = input;
this.dos = dos;
}
public void actionPerformed(ActionEvent ae) {
try {
dos.writeBytes(input.getText() + "\n");
input.setText("");
} catch(Exception e) {
System.out.println("Error writing to server output stream: " + e.getLocalizedMessage());
}
}
}
Here is the code for the Server:
import java.io.*;
import java.net.*;
import java.util.*;
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer ms = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
DatagramSocket ds = null;
try {
ds = new DatagramSocket(4);
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ds).start();
new MessageConnectionOut(client, ds).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionOut(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ds.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionIn(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ds.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
UPDATE:
I tried replacing all the DatagramSockets with MulticastSockets and adding it to a group when I declared it, MessageServer.main(). The same problem occurred.
Multicast code:
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer msgsrv = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
MulticastSocket ms = null;
try {
ms = new MulticastSocket(4);
ms.joinGroup(InetAddress.getByName("225.65.65.65"));
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ms).start();
new MessageConnectionOut(client, ms).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionOut(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ms.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
System.out.println("SENT_TO:" + this.getName());
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionIn(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ms.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
This sample may be help you out.
There is 2 threads for Server.
One for reading UDP messages. I used 2 different ports since I just want to avoid messages read by same process. I don't have 2 machines to test it. Tested on my local host.
Another thread will broadcast UDP messages received by reader thread.
There is a thread safe list which acts between threads as data sync. Received data added to the list. Broadcaster thread polling the list for the data, if there is any broadcast and else sleep for 500 microseconds. Threads are created using executor.
private final static String INET_ADDR = "224.0.0.3";
private final static int PORT1 = 8888;
private final static int PORT2 = 8889;
private static List<String> threadSafeList = null;
public static void main(String[] args) throws UnknownHostException, InterruptedException {
threadSafeList = new CopyOnWriteArrayList<String>();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Sender(InetAddress.getByName(INET_ADDR), PORT1));
executorService.submit(new Receiver(InetAddress.getByName(INET_ADDR), PORT2));
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver (InetAddress inetAddress, int port) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
//Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
threadSafeList.add(msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender (InetAddress inetAddress, int port) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Sender Address " + new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
while (true) {
try (DatagramSocket serverSocket = new DatagramSocket()) {
for (Iterator<String> it = threadSafeList.iterator(); !threadSafeList.isEmpty() && it.hasNext(); ) {
String i = it.next();
String msg = "Sent message no " + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(), msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
threadSafeList.remove(i);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
try {
System.out.println("going for sleep");
Thread.currentThread().sleep(500);
System.out.println("going for sleeping");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Design can be modified by changing the creation of sender thread. Whenever receiver thread gets a message, create a sender thread and do the broadcast and shutdown that thread. You can use reusable thread pool instead of fixed Thread pool what used in this example. And you can pass message as argument while you create sender thread (so list may not be needed at all) and do the submit. I do have code.
public static void main(String[] args) throws UnknownHostException,
InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Receiver(InetAddress.getByName(INET_ADDR),
PORT2, executorService));
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
And inner classes,
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
private ExecutorService executorService;
public Receiver(InetAddress inetAddress, int port,
ExecutorService executorService) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.executorService = executorService;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
executorService.submit(new Sender(InetAddress
.getByName(INET_ADDR), PORT1, msg));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
private String message;
public Sender(InetAddress inetAddress, int port, String message)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.message = message;
}
public void run() {
System.out.println(" # Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
try {
DatagramSocket serverSocket = new DatagramSocket();
String msg = "Sent message no " + message;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Client has got 2 threads,
One for reading broadcaster messages.
Another for sending 5 messages in loop. Once it is finished, thread will shut-down.
No data exchange here, so no thread safe list.
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Receiver ");
System.out.println(" # Receiver port " + this.port);
byte[] buf = new byte[256];
try (MulticastSocket clientSocket = new MulticastSocket(this.port)) {
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" # Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" # Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
try {
DatagramSocket serverSocket = new DatagramSocket();
for (int i = 0; i < 5; i++) {
System.out.println("inside loop");
String msg = "Sent message no 2" + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(
msg.getBytes(), msg.getBytes().length, this.addr,
this.port);
System.out.println("Before sending to socket");
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
This article sample code is extended further.
Code to be fine tuned.
I am writing a Server/Client chat where basically Multiple Clients connected to One Server. One client send a message to server Then all other Clients will get the same message. For example: Client A, B, C Connected to A same Server. Client A send Message To Server, Server then will send the same message to client B and C but exclude Client A.
I'm stuck at part where Server send out the message to all other clients.
Below is the code, I'm just a Java beginner so any help with the code will be much appreciate.
ServerSide
public class ServerP2P extends Thread{
private ServerSocket server = null;
private Socket clientSocket = null;
private ArrayList<ServerThread> clientThreadList = new ArrayList<>();
private int maxClient = 4;
private int port = 9990;
boolean listening = true;
public ServerP2P(){
try{
server = new ServerSocket(port);
}catch(IOException e){
e.printStackTrace();
return;
}
System.out.println("Server with Port "+port+" is Up and Running");
}
public void run(){
System.out.println("Room Chat Is Up");
while(listening){
for(int i = 0;i<clientThreadList.size();i++){
if(!clientThreadList.get(i).getConneection()){
System.out.println(clientThreadList.get(i)+" is removing from server because there is no conntection");
clientThreadList.remove(i);
}
}
try{
clientSocket = server.accept();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("User with IP "+clientSocket.getInetAddress()+" Has Connected to Server");
clientThreadList.add(new ServerThread(clientSocket));
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
}
}
public ArrayList<ServerThread> listOFClient(){
return clientThreadList;
}
public static void main(String[] args){
ServerP2P server = new ServerP2P();
server.start();
}
}
ServerThread
public class ServerThread{
private Socket clientSocket;
private boolean connected;
private Incomming incommingData;
String msg = null;
private class Incomming extends Thread{
private DataInputStream input;
public void run(){
try{
input = new DataInputStream(clientSocket.getInputStream());
}catch(IOException e){
e.printStackTrace();
return;
}
System.out.println("User with IP "+clientSocket.getInetAddress()+" has connected");
while(true){
try{
Thread.sleep(200);
int msgSize = input.readInt();
byte[] msgByte = new byte[msgSize];
for(int i = 0; i < msgSize ; i++){
msgByte[i] = input.readByte();
}
msg = new String(msgByte);
System.out.println(msg);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public ServerThread(Socket newClientSocket){
this.clientSocket = newClientSocket;
connected = true;
incommingData = new Incomming();
incommingData.start();
}
public boolean getConneection(){
return connected;
}
public void closeConnection(){
try{
connected = false;
clientSocket.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
ClientSide
public class ClientP2P{
private Socket serverSocket = null;;
private DataOutputStream output = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) {
ClientP2P client = new ClientP2P();
client.startConnect();;
}
public void startConnect(){
int port = 9990;
try {
serverSocket = new Socket("localhost", port);
System.out.println(serverSocket.isBound());
output = new DataOutputStream(serverSocket.getOutputStream());
System.out.println("Please Enter Your name: ");
String nameClient = reader.readLine();
output.writeInt(nameClient.length());
output.writeBytes(nameClient);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("You Are Connected");
System.out.println("Chat Can Start");
sendText();
}
public void sendText(){
try {
while (true) {
System.out.println("Type Message: ");
String msg = reader.readLine();
output.writeInt(msg.length());
output.writeBytes(msg);
System.out.println("Message sent");
recivedText();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void recivedText(){
try{
DataInputStream input = new DataInputStream(serverSocket.getInputStream());
int textSize = 0;
while(input.available() != 0){
byte[] byteString = new byte[textSize];
for(int i = 0; i < textSize;i++){
byteString[i] = input.readByte();
}
String txtServer = new String(byteString);
System.out.println(txtServer);
textSize = 0;
}
sendText();
}catch(Exception e){
e.printStackTrace();
}
}
}
Thanks For Your Time Guys.
Your ServerThread receives the messages and you want to send them to all other clients. One way you could achieve is to have the clients register themselves with the Server (this would help in the server not knowing the clients when it starts, which ideally should be the case). In your ServerThread, get a list of available clients from the server and loop through them and send the message to each one of them.
Use ObserverDesign pattern to hold the list of all your buddy/user to whom you wish to send message. Use HashMap to maintain a list of all the observer and its socket. Once the message is received, you retrieve the sockets of each user and write the same message on each socket.
i have 2 class
first class
import java.io.IOException;
import java.net.*;
public class Udp {
DatagramSocket socket = null;
DatagramPacket inPacket = null; // recieving packet
DatagramPacket outPacket = null; // sending packet
byte[] inBuf, outBuf;
InetAddress source_address = null;
public String Hasil = null;
String msg;
final int PORT = 8888;
public void received() {
try {
socket = new DatagramSocket(PORT);
while (true) {
System.out.println("Waiting for client...");
// Receiving datagram from client
inBuf = new byte[256];
inPacket = new DatagramPacket(inBuf, inBuf.length);
socket.receive(inPacket);
// Extract data, ip and port
int source_port = inPacket.getPort();
source_address = inPacket.getAddress();
msg = new String(inPacket.getData(), 0, inPacket.getLength());
// System.out.println("Client " + source_address + ":" + msg);
Hasil = msg;
// Send back to client as an echo
msg = reverseString(msg.trim());
outBuf = msg.getBytes();
outPacket = new DatagramPacket(outBuf, 0, outBuf.length,
source_address, source_port);
socket.send(outPacket);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("Client " + source_address + ":" + msg);
}
private static String reverseString(String input) {
StringBuilder buf = new StringBuilder(input);
return buf.reverse().toString();
}}
and second class
public class main {
public static void main(String[] args) {
Udp u = new Udp();
u.received();
System.out.println(u.Hasil + " " + u.source_address);
}
}
why when i run this porgram, udp is start , but String Hasil not comming,
how i can get String Hasil in statement While (true) ?
your string may null try this structure:
while(true){
while(hasil==null){
}
}
You need seperate threads:
public class Udp implements Runnable {
boolean running = false;
...
while(running) { // <-- this was your while (true) {
...
#Override
public void run {
running = true
received();
}
public void stop() {
running = false;
}
}
and in your main
...
new Thread(u).start();
while(u.Hasil != null){
try{
Thread.currentThread().sleep(1);//sleep for 1 ms
}
catch(ItrerruptedException ie){
//ignore
}
}
yeah i know the style is ugly ;)