I have a server listening to two different ports, after a connection is accepted, it saves the combination nameOfClient - Socket into an hashMap.
After that it starts a method in a loop to check which client is sending a message and who is the receiver of that message, it retrieves the the socket value from the hash map and use it to initialize a DataOutputStream to that socket.
The problem is that the server only receives the first two messages and they contain strange values. eg. Client 1 writeInt(1) to the server but on the other side an apparently random value is received.
The class sending data is:
public class Game {
List <Player> players = new ArrayList<Player>();
int size;
public Game() {
(...game code here...)
public void sendUpdatedTableValues(int nP, int nF, int nS, int sc)
{
/* string,byte,stringa,primitivo del messaggio
string - mittente; byte - tipo di messaggio; stringa - ricevente; prim - messaggio
*/
try {
DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream());
dataOut.writeUTF("Pista " + Lane.laneNum);
dataOut.writeInt(1);
dataOut.writeUTF("Amministrazione");
dataOut.writeInt(nP);
dataOut.writeUTF("-");
dataOut.writeInt(nF);
dataOut.writeUTF("-");
dataOut.writeInt(nS);
dataOut.writeUTF("-");
dataOut.writeInt(sc);
dataOut.flush();
} catch (IOException ex) {
Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* This method send the player's number of strikes
* this method has ID byte = 3
* #param nP - Player Number
* #param nS - Strike Number
*/
public void sendStrikeCounter(int nP, int nS)
{
try {
DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream());
dataOut.writeUTF("Pista " + Lane.laneNum);
dataOut.writeInt(3);
dataOut.writeUTF("Amministrazione");
dataOut.writeInt(nP);
dataOut.writeUTF("-");
dataOut.writeInt(nS);
dataOut.flush();
} catch (IOException ex) {
Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* This method updates result table on server
* this method has ID byte= 4
* #param nP - Player Number
* #param nF - Frame Number
* #param res - Frame result
*/
public void sendUpdatedResultsTable(int nP, int nF, int res)
{
try {
DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream());
dataOut.writeUTF("Pista " + Lane.laneNum);
dataOut.writeInt(4);
dataOut.writeUTF("Amministrazione");
dataOut.writeInt(nP);
dataOut.writeUTF("-");
dataOut.writeInt(nF);
dataOut.writeUTF("-");
dataOut.writeInt(res);
dataOut.flush();
} catch (IOException ex) {
Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* This method send the player's number of spares
* this method has ID byte = 5
* #param nP - Player Number
* #param nS - Spare Number
*/
public void sendSpareCounter(int nP, int nS)
{
try {
DataOutputStream dataOut = new DataOutputStream(Lane.socket.getOutputStream());
dataOut.writeUTF("Pista " + Lane.laneNum);
dataOut.writeInt(5);
dataOut.writeUTF("Amministrazione");
dataOut.writeInt(nP);
dataOut.writeUTF("-");
dataOut.writeInt(nS);
dataOut.flush();
} catch (IOException ex) {
Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
}
}
The code for the server is:
public class Server {
public static List <Player> players = new ArrayList <Player> ();
public static HashMap <String, List<Player>> laneHashMap = new HashMap<String, List<Player>>();
ServerSocket adminListener;
ServerSocket clientListener;
public static void main(String[] args) throws IOException {
System.out.println("Server bowling avviato:\n");
Server server = new Server();
/**
* The port 9090 is reserved for the admin client, the other port is
* used by all the lane clients
*/
server.adminListener = new ServerSocket(9090);
server.clientListener = new ServerSocket(9898);
int clientNumber = 1; //Used to keep track of every single lane
//Create an HashMap used to store the name and the socket of the clients
HashMap<String, Socket> socketMap = new HashMap<>();
/**
* The server starts two different threads that keep listening for
* incoming connections
*/
new threadAdminPort(server.adminListener, socketMap).start();
new threadClientPort(server.clientListener, socketMap, clientNumber).start();
}
/**
* Used to listen to port 9090
*/
private static class threadAdminPort extends Thread {
private ServerSocket adminListener;
private HashMap<String, Socket> socketMap;
public threadAdminPort(ServerSocket adminListener, HashMap<String, Socket> socketMap) {
this.adminListener = adminListener;
this.socketMap = socketMap;
}
#Override
public void run() {
try {
while (true) {
new Handler(adminListener.accept() , socketMap).start();
}
} catch (IOException e) {
System.out.println("Errore di accept: " + e);
} finally {
try {
adminListener.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
/**
* Used to listen to port 9898
*/
private static class threadClientPort extends Thread {
private ServerSocket clientListener;
private HashMap<String, Socket> socketMap;
private int clientNumber;
public threadClientPort(ServerSocket clientListener , HashMap<String, Socket> socketMap , int clientNumber) {
this.clientListener = clientListener;
this.socketMap = socketMap;
this.clientNumber = clientNumber;
}
#Override
public void run() {
try {
while (true) {
new Handler(clientListener.accept() , socketMap , clientNumber++).start();
}
} catch (IOException e) {
System.out.println("Errore di accept: " + e);
} finally {
try {
clientListener.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
/**
* A private thread to handle requests on a particular socket.
*/
private static class Handler extends Thread {
Socket socket;
HashMap<String, Socket> socketMap;
int clientNumber;
//Set true only if it is received a endOfGame message
boolean endOfGame = false;
/**
* This constructor is meant to be used by the lane clients.
*/
public Handler(Socket socket, HashMap<String, Socket> socketMap , int clientNumber) throws IOException {
this.socket = socket;
this.socketMap = socketMap;
this.clientNumber = clientNumber;
String clientName = "Pista " + clientNumber;
synchronized(socketMap) {
socketMap.put(clientName, socket);
}
//Send laneNum to the client
DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream());
dataOut.writeInt(clientNumber);
System.out.println("- Pista " + clientNumber + " connessa -\nPronta per giocare");
}
/**
* This constructor is meant to be used by the admin client as it
* provides no clientNumber variable.
*/
public Handler(Socket socket , HashMap<String, Socket> socketMap) {
this.socket = socket;
this.socketMap = socketMap;
String clientName = "Amministrazione";
synchronized (socketMap) {
socketMap.put(clientName, socket);
}
System.out.println("- Client Amministrazione connesso -");
}
/**
* This function is shared by both the admin client and the lane clients
*/
#Override
public void run() {
forwardMessage();
try {
socket.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
if(clientNumber==0)
System.out.println("Connessione con il client amministrazione terminata");
else
System.out.println("Connessione con il client " + clientNumber + " terminata");
}
private void forwardMessage () {
Set set = socketMap.entrySet();
Iterator iterator = set.iterator();
//The following are the fixed fields of a message
String sender = null;
String receiver = null;
int messageType = 100;
//while(iterator.hasNext())
while(true){
for(Map.Entry<String, Socket> entry : socketMap.entrySet()){
// Map.Entry mapEntry = (Map.Entry)iterator.next();
Socket tempRecSocket = (Socket) entry.getValue();
System.out.println("Il valore di tempRecSocket è "+ tempRecSocket);
DataInputStream dataIn;
DataOutputStream dataOut;
try {
dataIn = new DataInputStream(tempRecSocket.getInputStream());
//Analyze and understand what type of message it is and who is
//the sender and the receiver
sender = dataIn.readUTF();
messageType = dataIn.readInt();
System.out.println("Sender ricevuto "+ sender);
receiver = dataIn.readUTF();
System.out.println("Receiver ricevuto " + receiver);
switch (messageType) {
case 0:
{
//player 1
boolean start = dataIn.readBoolean();
String namezero = dataIn.readUTF();
int shoeszero = dataIn.readInt();
String cf = dataIn.readUTF();
//player 2
int shoesone = dataIn.readInt();
String nameone = dataIn.readUTF();
//player 3
int shoestwo = dataIn.readInt();
String nametwo = dataIn.readUTF();
//player 4
int shoesthree = dataIn.readInt();
String namethree = dataIn.readUTF();
//player 5
int shoesfour = dataIn.readInt();
String namefour = dataIn.readUTF();
//player 6
int shoesfive = dataIn.readInt();
String namefive = dataIn.readUTF();
laneHashMap.put(receiver, players); //insert in hashmap lane data
laneHashMap.get(receiver).add(new Player(0,namezero,shoeszero,cf)); //add player0 in players list7
laneHashMap.get(receiver).add(new Player(1,shoesone,nameone));
laneHashMap.get(receiver).add(new Player(2,shoestwo,nametwo));
laneHashMap.get(receiver).add(new Player(3,shoesthree,namethree));
laneHashMap.get(receiver).add(new Player(4,shoesfour,namefour));
laneHashMap.get(receiver).add(new Player(5,shoesfive,namefive));
Socket tempSndSocket = (Socket) socketMap.get(receiver);
System.out.println("Il valore di tempSndSocket è "+ tempSndSocket);
dataOut = new DataOutputStream(tempSndSocket.getOutputStream());
dataOut.writeUTF(sender);
dataOut.writeInt(messageType);
if(messageType!=0)
System.out.println("Valore di messageType "+ messageType);
dataOut.writeUTF(receiver);
dataOut.writeBoolean(start);
for (int i = 0;i<6;i++)
{
laneHashMap.get(receiver).get(i).setInitialTable();
dataOut.writeUTF(laneHashMap.get(receiver).get(i).getName());
dataOut.writeInt(0); //separatore
} dataOut.flush();
// dataOut.close();
System.out.println("Il server ha inviato correttamente il messaggio di tipo 0");
break;
}
case 1:
{
System.out.println("Il server ha ricevuto correttamente il messaggio di tipo 1 ed ora provvederà all'invio");
//sendUpdatedTableValues
int playerNumber = dataIn.readInt();
dataIn.readUTF();
int frameNumber = dataIn.readInt();
dataIn.readUTF();
int shotNumber = dataIn.readInt();
dataIn.readUTF();
int score = dataIn.readInt();
System.out.println("Ho ricevuto: 1 - "+ playerNumber + "2 - framenumber "+ frameNumber+ "3 - shotNumber" + shotNumber+ "4 - score "+ score);
//update local player data
laneHashMap.get(sender).get(playerNumber).setTable(frameNumber, shotNumber, score);
System.out.println("In questo turno il giocatore ha totalizzato "+ laneHashMap.get(sender).get(playerNumber).getTable(frameNumber, shotNumber));
Socket tempSndSocket = (Socket) socketMap.get(receiver);
dataOut = new DataOutputStream(tempSndSocket.getOutputStream());
dataOut.writeUTF(sender);
dataOut.writeInt(messageType);
dataOut.writeUTF(receiver);
dataOut.writeInt(playerNumber);
dataOut.writeUTF("-");
dataOut.writeInt(frameNumber);
dataOut.writeUTF("-");
dataOut.writeInt(shotNumber);
dataOut.writeUTF("-");
dataOut.writeInt(score);
break;
}
break;
}
There's another class in the same package of Game.java that connects to the server. The game is started succesfully by another client, after that the messages cannot be correctly received.
As stated in comments, your reads and writes are not symmetrical. If you call writeInt() there must be a corresponding readInt(). If you call writeUTf() there must be a corresponding readUTF(). And so on for all the other datatypes. And all these things must happen in the same order at both ends.
Related
I have a simple parking-lot simulation which simulates the entry and exit of customers. A class called entrySimulation is used as the producer and the exitSimulation consumes the message and peforms checks to see if a customer should enter.The entry simulation class is as follows:
package parking.experiment_2;
public class entrySimulation implements Runnable {
public static void main(String[] args) {
ScheduledExecutorService entrySimulation = Executors.newScheduledThreadPool(1);
entrySimulation.scheduleAtFixedRate(new entrySimulation(), 2, 4, TimeUnit.SECONDS);
}
///PRODUCER CLASS
int numOfRuns = 100;//1000 runs
public securityGuard_exp_1 myGuard = new securityGuard_exp_1();
//System.out.println("Customer Exiting");
//Thread.sleep(randomTime.nextInt(5000));
public meterClass_exp_1 myMeter = new meterClass_exp_1();
//Details are only set if there is space available
//The assumption is that users cannot stay longer than 2 days. The reality-to-simulation time ratio is 1 unit:10min
//instantiation of the info generator class
public infoGenerator_exp_1 info = new infoGenerator_exp_1();
//Generating random Car info
//spot_exp_1 mySpot = new spot_exp_1();
//Use an iterator
public List<ticketClass_exp_1> ticketArray = new ArrayList<>();
Iterator<ticketClass_exp_1> iter = ticketArray.iterator();
public final spot_exp_1 availableSpot = new spot_exp_1();
//Random time generator
Random randomTime = new Random();
//List<Employee> empList = new ArrayList<>();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos;
{
try {
oos = new ObjectOutputStream(bos);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public List<ticketClass_exp_1> randomEntry() throws IOException, TimeoutException {
Gson gson = new GsonBuilder().create();
carClass_exp_2 car = null;
String queueName = "exitQueue";
String message = null;
for (int currentRuns = 0; currentRuns < numOfRuns; currentRuns++) {
String plateNumber = info.plateGenerator();
String carModel = info.modelGenerator();
String color = info.colorGenerator();
myMeter.setPurchasedMinutes(randomTime.nextInt(30));
carClass_exp1_1 vehicle = new carClass_exp1_1(carModel, color, plateNumber, randomTime.nextInt(2880));
ticketClass_exp_1 myTicket = myGuard.ticketGenerator(vehicle, myMeter);
//Generating details
myTicket.setmeter(myMeter);
myTicket.setCar(vehicle);
myTicket.getCar().plateSetter(plateNumber);
myTicket.getCar().colorSetter(color);
myTicket.getCar().modelSeter(carModel);
//myTicket.getGuard().setguardName("Phill");
//myTicket.getGuard().setBadgeNumber("AF170");
int spotAvail = availableSpot.assignSpot();
myTicket.setSlotNum(spotAvail);
message = gson.toJson(myTicket);
ticketArray.add(myTicket);
return ticketArray;
}
public void publishMessage( ticketClass_exp_1 tickArray ) throws IOException, TimeoutException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(tickArray);
///Direct exchange from enrtySimulation to exit simulation -Used to inform customer exit
//Topic exchange from entrySimulation to individual car park types . EG: Mercedes benz lot, SRT lot, ...
String exchangeName = "entryExchange";
String routingKey = "exitKey";
//Creating a connection factory
ConnectionFactory factory = new ConnectionFactory();
try(Connection conVar = factory.newConnection()){
Channel channelCon = conVar.createChannel();
//Exchange declaration
channelCon.exchangeDeclare(exchangeName,"customerEntry");
channelCon.basicPublish(exchangeName,routingKey,null,bos.toByteArray());
//System.out.println(message);
System.out.println("Customer Entered");
}catch(Exception e){}
}
#Override
public void run() {
ticketClass_exp_1 message = null;
try {
message = (ticketClass_exp_1) randomEntry();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
//Publishing message
try {
publishMessage(message);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
}
}
The consumer then consumes the array as follows;
public class exitSimulation implements Runnable {
//public exitSimulation(Channel channel) {
//super(channel);
//String storedMessage;
//}
public String reciver() throws Exception {
ConnectionFactory factory = new ConnectionFactory();
Connection connection = factory.newConnection();
//Creat connection
Channel channel = connection.createChannel();
//create channel
String recievQueue = channel.queueDeclare().getQueue();
System.out.println(" Awaiting Cars");
consumeConvert consumer=new consumeConvert(channel);
channel.basicConsume(recievQueue,true,consumer);
// using
return consumer.getFormatMessage();
}
public class consumeConvert extends DefaultConsumer {
private String storedMessage;
public consumeConvert(Channel channelReceiver) {
super(channelReceiver);
}
public String getFormatMessage() {
return storedMessage;
}
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] messageBody)
throws IOException {
String message = new String(messageBody, "UTF-8");
System.out.println(" MSG RECIEVED: " + message + "'");
storedMessage = message; // store message here
}
}
public static void main(String[] args) {
//Receives message when customers are entering - Contains customer information e.g. customer x is entering.. details ....
// Adds them to a local array
// IF any customers checkParking(ExitCar, meterOut) == true : CUSTOMER EXITS
//
//
//Get the messages and pass as function inputs
/*
*
public class MyConsumer extends DefaultConsumer {
private String storedMessage;
public MyConsumer(Object channelRecv) {
super(channelRecv);
}
public String getStoredMessage() {
return storedMessage;
}
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
storedMessage = message; // store message here
}
}
*
*
* Perfrom checks and send exiting car
* */
//String qName = channelCon.queueDeclare().getQueue();
//Binding the queue
//channelCon.queueBind(qName, exchangeName, routingKey);
Collection<ticketClass_exp_2> ticketArray = new ArrayList<ticketClass_exp_2>();
int availableSpot = 0;
Random randomTime = new Random();
//System.out.println(availableSpot.getSpotNum());
for (ticketClass_exp_2 tick : ticketArray) {
if (ticketArray.size() != 0) {
meterClass_exp_2 meterOut = tick.getMeter();
carClass_exp_2 ExitCar = tick.getCar();
securityGuard_exp_2 myGuard2 = new securityGuard_exp_2();
//System.out.println("IND" + tick.slotNum);
if (myGuard2.checkParking(ExitCar, meterOut)) {
try {
Thread.sleep(randomTime.nextInt(2000));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("\nCustomer " + ExitCar.plateGetter() + " is exiting the carpark...");
double penaltyVal = tick.getPenalty();
System.out.println("FINE: " + penaltyVal);
System.out.println("==================================================================");
}
}
if (availableSpot == 16) {
System.out.println("Carpark full, No cars allowed unitl a space is free");
//Send a message
//System.out.println("Total Waiting customers: " + bouncedCustomers);
}
//} catch (Exception e) {
//}
//currentRuns += 1;
///Thread.join(5000);
}
}
The array recived is of type ticketArray. How can I make this work please?
Any enhancement recommendations are welcome
MessageCreator: Encapsulate and resolve ports and device unique identifiers.
public class MessageCreator {
private static final String HEADER_PORT = "to port:";
private static final String HEADER_SN = "My sn:";
public static String buildWithPort(int port) {
return HEADER_PORT + port;
}
public static int parsePort(String data) {
if (data.startsWith(HEADER_PORT)) {
return Integer.parseInt(data.substring(HEADER_PORT.length()));
}
return -1;
}
public static String buildWithSn(String sn) {
return HEADER_SN + sn;
}
public static String parseSn(String data) {
if (data.startsWith(HEADER_SN)) {
return data.substring(HEADER_SN.length());
}
return null;
}
}
UdpProvider: Loop to listen to a specific port, then parse the received data, determine whether the data conforms to the predetermined format, get the sender's response port from it, and respond with the uniquely identified UUID value to the UDP searcher.
public class UdpProvider {
public static void main(String[] args) throws IOException {
String sn = UUID.randomUUID().toString();
Provider provider = new Provider(sn);
provider.start();
// Warning: Result of 'InputStream.read()' is ignored
System.in.read();
provider.exit();
}
private static class Provider extends Thread {
private DatagramSocket ds = null;
private boolean done = false;
private final String sn;
public Provider(String sn) {
super();
this.sn = sn;
}
#Override
public void run() {
super.run();
try {
ds = new DatagramSocket(20000);
while (!done) {
final byte[] buf = new byte[512];
DatagramPacket receivePak = new DatagramPacket(buf, buf.length);
ds.receive(receivePak);
String ip = receivePak.getAddress().getHostAddress();
int port = receivePak.getPort();
byte[] receivePakData = receivePak.getData();
String receiveData = new String(receivePakData, 0, /*receivePakData.length*/receivePak.getLength());
System.out.println("received from -> ip: " + ip + ", port: " + port + ", data: " + receiveData);
int responsePort = MessageCreator.parsePort(receiveData.trim());
if (responsePort != -1) {
String responseData = MessageCreator.buildWithSn(sn);
byte[] bytes = responseData.getBytes(StandardCharsets.UTF_8);
DatagramPacket responsePak = new DatagramPacket(bytes, bytes.length,
/*InetAddress.getLocalHost()*/
receivePak.getAddress(),
responsePort);
ds.send(responsePak);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close();
}
}
public void exit() {
done = true;
close();
}
public void close() {
if (ds != null) {
ds.close();
ds = null;
}
}
}
}
UdpSearcher: Listening to a specific port and sending a LAN broadcast, sending a broadcast sets the listening port in the data, so you need to turn on listening first to finish before you can send a broadcast, and once you receive the response data, you can parse the device information
public class UdpSearcher {
private static final int LISTENER_PORT = 30000;
public static void main(String[] args) throws IOException, InterruptedException {
Listener listener = listen();
sendBroadcast();
// Warning: Result of 'InputStream.read()' is ignored
System.in.read();
List<Device> deviceList = listener.getDevicesAndClose();
for (Device device : deviceList) {
System.out.println(device);
}
}
public static void sendBroadcast() throws IOException {
DatagramSocket ds = new DatagramSocket();
String sendData = MessageCreator.buildWithPort(LISTENER_PORT);
byte[] sendDataBytes = sendData.getBytes(StandardCharsets.UTF_8);
DatagramPacket sendPak = new DatagramPacket(sendDataBytes, sendDataBytes.length);
sendPak.setAddress(InetAddress.getByName("255.255.255.255"));
sendPak.setPort(20000);
ds.send(sendPak);
ds.close();
}
public static Listener listen() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
Listener listener = new Listener(LISTENER_PORT, countDownLatch);
listener.start();
countDownLatch.await();
return listener;
}
private static class Listener extends Thread {
private final int listenPort;
private DatagramSocket ds = null;
private boolean done = false;
private final CountDownLatch countDownLatch;
private List<Device> devices = new ArrayList<>();
public Listener(int listenPort, CountDownLatch countDownLatch) {
super();
this.listenPort = listenPort;
this.countDownLatch = countDownLatch;
}
#Override
public void run() {
super.run();
countDownLatch.countDown();
try {
ds = new DatagramSocket(listenPort);
while (!done) {
final byte[] buf = new byte[512];
DatagramPacket receivePak = new DatagramPacket(buf, buf.length);
ds.receive(receivePak);
String ip = receivePak.getAddress().getHostAddress();
int port = receivePak.getPort();
byte[] data = receivePak.getData();
String receiveData = new String(data, 0, /*data.length*/receivePak.getLength());
String sn = MessageCreator.parseSn(receiveData);
System.out.println("received from -> ip: " + ip + ", port: " + port + ", data: " + receiveData);
if (sn != null) {
Device device = new Device(ip, port, sn);
devices.add(device);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close();
}
}
public void close() {
if (ds != null) {
ds.close();
ds = null;
}
}
public List<Device> getDevicesAndClose() {
done = true;
close();
return devices;
}
}
private static class Device {
private String ip;
private int port;
private String sn;
public Device(String ip, int port, String sn) {
this.ip = ip;
this.port = port;
this.sn = sn;
}
#Override
public String toString() {
return "Device{" +
"ip='" + ip + '\'' +
", port=" + port +
", sn='" + sn + '\'' +
'}';
}
}
}
UdpProvider and UdpSearcher worked fine and printed corrresponding data until I input a char sequence from keyboard follwed by pressing Enter key on each console window, both threw an exception on this line ds.receive(receivePak); :
I'm using a java server to facilitate online multiplayer in my game made with GameMaker Studio, the players will send data to the java server which will process the data and send it to the players. The problem is that when a player with a slow internet connection is not being able to handle the amount of data being send to it, it will cause the server to freeze for all players (the server will no longer process any data send by other players).
I have simulated slow internet speeds by using NetLimiter and setting the download speed of one laptop at 5 kb/s, while maintaining proper speed at other laptops. I have tried to send ACK packets from the java server to the client and if it doesn't respond in 1 second no more data will be send to that client (and eventually the client will be kicked). This has reduced the chance of freezing the server, but it will still happen occasionally.
Main.java
import java.net.Socket;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import java.io.IOException;
import java.util.HashMap;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;
public class Main
{
static ServerSocket serverSocket_;
static HashMap<String, ServerInformation> servers_;
static int verboseLevel_;
static int threadTimeout_;
static int masterPort_;
static int serverNumber_;
static int socketTimeOut_;
static {
Main.serverSocket_ = null;
Main.servers_ = new HashMap<String, ServerInformation>();
Main.verboseLevel_ = 5;
Main.threadTimeout_ = 10;
Main.masterPort_ = 6510;
Main.serverNumber_ = 1;
Main.socketTimeOut_ = 6000;
}
public static void main(final String[] args) {
try {
setupServerAndCleanup(Main.masterPort_);
while (true) {
handleIncomingConnection();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
static void setupServerAndCleanup(final int port) throws IOException {
(Main.serverSocket_ = new ServerSocket()).setReuseAddress(true);
Main.serverSocket_.bind(new InetSocketAddress(Main.masterPort_));
System.out.println("Server socket up and running on port " + Main.masterPort_);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
if (Main.serverSocket_ != null) {
try {
Main.serverSocket_.close();
System.out.println("Server socket closed, port released");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}));
}
static void handleIncomingConnection() throws IOException {
final Socket clientSocket = Main.serverSocket_.accept();
clientSocket.setSoTimeout(Main.socketTimeOut_);
final ClientThread client = new ClientThread(clientSocket);
client.start();
}
}
ClientThread.java
Case 1 is the part dealing with sending data to the clients, in particular this line:
thread2.out_.print(msg);
If more data is being send than one client can handle the server will freeze for all other clients as well.
import java.util.Iterator;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class ClientThread extends Thread
{
Socket clientSocket_;
String clientIp_;
String serverIp_;
ServerInformation server_;
PrintWriter out_;
BufferedReader in_;
boolean prepareTermination_;
boolean terminated_;
private static final Pattern numberPattern;
static {
numberPattern = Pattern.compile("\\d+");
}
public ClientThread(final Socket sock) {
this.clientSocket_ = sock;
this.clientIp_ = this.clientSocket_.getRemoteSocketAddress().toString();
this.serverIp_ = null;
this.server_ = null;
this.prepareTermination_ = false;
this.terminated_ = false;
}
#Override
public void run() {
try {
this.out_ = new PrintWriter(this.clientSocket_.getOutputStream(), true);
this.in_ = new BufferedReader(new InputStreamReader(this.clientSocket_.getInputStream()));
long lastActionTime = System.currentTimeMillis();
while (true) {
if (this.in_.ready() || System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
if (System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
//this.logDebugMessage(3, "Thread was killed due to prolonged inactivity (" + Main.threadTimeout_ + " seconds)");
this.terminateThread();
return;
}
final String tempInputLine;
if(((tempInputLine = this.in_.readLine()) == null )){
this.terminateThread(); //end thread
return;
}
else
{
lastActionTime = System.currentTimeMillis();
final String inputLine = tempInputLine.trim();
if (ClientThread.numberPattern.matcher(inputLine).matches()){
final int val = Integer.parseInt(inputLine);
switch (val) {
case 1: { //send data to other players
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int j = 0; j < parseCount; ++j) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(msg);
thread2.out_.flush();
}
}
//this.logDebugMessage(5, "Packet for others: '" + msg.toString() + "'");
break;
}
case 2: { //remove game server
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(this.server_.ip_);
this.serverIp_ = null;
for (final ClientThread thread : this.server_.ipToClientThread_.values()) {
thread.prepareTermination_ = true;
}
this.terminateThread();
return;
}
case 3: { //connect new client
final String ipServer = this.in_.readLine().trim();
final String ipClient = this.in_.readLine().trim();
this.logDebugMessage(1, "A client wishes to connect to a server, client: " + ipClient + ", server: " + ipServer);
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
if (info == null) {
System.out.println("Connection to the server failed, no such server in the server list");
this.out_.print("*" + 1 + "|" + 1 + "~" + "|");
this.out_.flush();
break;
}
this.server_ = info;
this.server_.ipToClientThread_.put(ipClient, this);
this.logDebugMessage(1, "Connection success");
this.logDebugMessage(5,"Map: " + this.server_.ipToClientThread_);
this.out_.print("*" + 1 + "|" + 2 + "~" + "|");
this.out_.flush();
break;
}
case 4: { //disconnect client
final String ipClient = this.in_.readLine().trim();
this.server_.ipToClientThread_.remove(ipClient);
this.logDebugMessage(1, String.valueOf(ipClient) + " disconnected from the server at " + this.server_.ip_);
this.serverIp_ = null;
this.terminateThread();
return;
}
case 5: { //host create new game
if (Main.serverNumber_ > 1000000) {
Main.serverNumber_ = 10;
}
Main.serverNumber_ += 1;
final String ipServer = Integer.toString(Main.serverNumber_); //unique server number
final String ipHost = this.in_.readLine().trim(); //host
final String name = this.in_.readLine().trim(); //Server name
final String description = this.in_.readLine().trim(); //class
final String servervar1 = this.in_.readLine().trim(); //max players
final String servervar3 = this.in_.readLine().trim(); //current lap
final String servervar4 = this.in_.readLine().trim(); //total laps
final String servervar5 = this.in_.readLine().trim(); //status
final String servervar6 = this.in_.readLine().trim(); //Password
final String servervar7 = this.in_.readLine().trim(); //Online version
final String servervar8 = this.in_.readLine().trim(); //Game server
final long servervar9 = System.currentTimeMillis(); //server creation time
//this.logDebugMessage(1, "A game server has been registered, ip: " + ipServer + ", name: " + name + ", description: " + description + ", servervar1: " + servervar1);
final ServerInformation gameServer = new ServerInformation(name, servervar1, servervar3, servervar4, servervar5, servervar6, servervar7, servervar8, servervar9, ipHost, ipServer, this.clientSocket_, this.out_, this.in_);
gameServer.description_ = description;
gameServer.ipToClientThread_.put(ipHost, this);
this.server_ = gameServer;
Main.servers_.put(ipServer, gameServer);
this.serverIp_ = ipServer;
break;
}
default: {
this.logDebugMessage(0, "Unrecognized case: '" + inputLine + "', " + val);
break;
}
}
}
else if (inputLine.length() > 0) {
this.logDebugMessage(0, "Unformated '" + inputLine + "'");
if (this.server_ != null) {
this.server_.out_.print(inputLine);
this.server_.out_.flush();
}
}
if (this.prepareTermination_) {
this.terminateThread();
return;
}
continue;
}
}
}
}
catch (SocketTimeoutException e) {
e.printStackTrace();
try {
this.terminateThread();
}
catch (IOException e2) {
e2.printStackTrace();
}
}
catch (IOException e3) {
e3.printStackTrace();
try {
this.terminateThread();
}
catch (IOException e4) {
e4.printStackTrace();
}
}
}
//debug messages
void logDebugMessage(final int requiredVerbose, final String msg) {
if (Main.verboseLevel_ >= requiredVerbose) {
System.out.println("[" + this.clientIp_ + "] " + msg);
}
}
//terminate thread
void terminateThread() throws IOException {
if (!this.terminated_) {
if (this.serverIp_ != null) {
Main.servers_.remove(this.serverIp_);
}
this.clientSocket_.close();
this.in_.close();
this.out_.close();
this.logDebugMessage(3, "Cleanup successful");
this.terminated_ = true;
}
}
}
How to avoid the server from freezing if more data is being send to a client than it can handle, so that the server can continue sending data to the other clients?
Edit
So I have tried using ExecutorService, but I must be doing something completely wrong because no data is being send by the java server.
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
thread2.out_.print(msg);
thread2.out_.flush();
}
});
executorService.shutdown();
}
}
It would be great if you could show me how to implement ExecutorService the right way.
If a delay in the client processing doesn't matter, this part should be done in a distinct flow execution for each client :
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print(msg);
thread2.out_.flush();
}
For example :
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
new Thread(()-> {
thread2.out_.print(msg);
thread2.out_.flush();
})
.start();
}
}
Note that creating Threads has a cost. Using ExecutorService could be a better idea.
I got one example of SNMPV3 trap,it is working fine when i use DefaultUdpTransportMapping but when i use DefaultTcpTransportMapping ,it will return null response event.
I have also attached code below .
public class SnmpUtilSendTrapV3 {
private Snmp snmp = null;
private Address targetAddress = null;
// private TcpAddress targetAddress = null;
public void initComm() throws IOException {
targetAddress = new TcpAddress(Inet4Address.getLocalHost(), 162);
// targetAddress = GenericAddress.parse("127.0.0.1/162");
TransportMapping transport = new DefaultTcpTransportMapping();
snmp = new Snmp(transport);
snmp.listen();
}
/**
* send trap
*
* #throws IOException
*/
public void sendPDU() throws IOException {
UserTarget target = new UserTarget();
target.setAddress(targetAddress);
target.setRetries(2);
target.setTimeout(1500);
// snmp version
target.setVersion(SnmpConstants.version3);
// target.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setSecurityName(new OctetString("MD5DES"));
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(
MPv3.createLocalEngineID()), 0);
usm.setEngineDiscoveryEnabled(true);
SecurityModels.getInstance().addSecurityModel(usm);
UsmUser user = new UsmUser(new OctetString("MD5DES"), AuthMD5.ID,
new OctetString("MD5DESUserAuthPassword"), PrivDES.ID,
new OctetString("MD5DESUserPrivPassword"));
snmp.getUSM().addUser(new OctetString("MD5DES"), user);
// create PDU
ScopedPDU pdu = new ScopedPDU();
pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3.0"),
new OctetString("DemoTrapv3")));
pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"),
new OctetString("Demo")));
pdu.setType(PDU.TRAP);
// send PDU to Agent and recieve Response
ResponseEvent respEvnt = snmp.send(pdu, target);
// analyze Response
if (respEvnt != null && respEvnt.getResponse() != null) {
Vector<VariableBinding> variableBindings = (Vector<VariableBinding>) respEvnt
.getResponse().getVariableBindings();
Vector<VariableBinding> recVBs = variableBindings;
for (int i = 0; i < recVBs.size(); i++) {
VariableBinding recVB = recVBs.elementAt(i);
System.out
.println(recVB.getOid() + " : " + recVB.getVariable());
}
}
snmp.close();
}
public static void main(String[] args) {
try {
SnmpUtilSendTrapV3 util = new SnmpUtilSendTrapV3();
util.initComm();
util.sendPDU();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MultiThreadedTrapReceiver implements CommandResponder {
private Address address = GenericAddress.parse("0.0.0.0/162");
private int numDispatcherThreads = 2;
private OID authProtocol = AuthMD5.ID;
private OID privProtocol = PrivDES.ID;
private OctetString securityName = new OctetString("MD5DES");
private OctetString privPassphrase = new OctetString(
"MD5DESUserPrivPassword");
private OctetString authPassphrase = new OctetString(
"MD5DESUserAuthPassword");
public MultiThreadedTrapReceiver() {
try {
listen();
} catch (IOException ex) {
System.out.println(ex);
}
}
public synchronized void listen() throws IOException {
AbstractTransportMapping transport;
if (address instanceof TcpAddress) {
transport = new DefaultTcpTransportMapping((TcpAddress) address);
} else {
transport = new DefaultUdpTransportMapping((UdpAddress) address);
}
ThreadPool threadPool = ThreadPool.create("DispatcherPool",
numDispatcherThreads);
MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(
threadPool, new MessageDispatcherImpl());
// add message processing models
mtDispatcher.addMessageProcessingModel(new MPv1());
mtDispatcher.addMessageProcessingModel(new MPv2c());
mtDispatcher.addMessageProcessingModel(new MPv3(new OctetString(MPv3
.createLocalEngineID()).getValue()));
// add all security protocols
SecurityProtocols.getInstance().addDefaultProtocols();
SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());
Snmp snmp = new Snmp(mtDispatcher, transport);
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(
MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
// Add the configured user to the USM
addUsmUser(snmp);
snmp.addCommandResponder(this);
transport.listen();
try {
this.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
private void addUsmUser(Snmp snmp) {
snmp.getUSM().addUser(
securityName,
new UsmUser(securityName, authProtocol, authPassphrase,
privProtocol, privPassphrase));
}
#Override
public void processPdu(CommandResponderEvent respEvnt) {
System.out.println(respEvnt.getPDU());
InetAddress pduAgentAddress = null;
// System.out.println(respEvnt.getPDU() + " recieved;");
// this.setPdu(respEvnt.getPDU());
OctetString community = new OctetString(respEvnt.getSecurityName());
System.out.println("community: " + community.toString());
// handle the SNMP v1
if (respEvnt.getPDU().getType() == PDU.V1TRAP) {
Address address = respEvnt.getPeerAddress();
String hostName = address.toString().split("/")[0];
int nPort = Integer.parseInt(address.toString().split("/")[1]);
try {
pduAgentAddress = InetAddress.getByName(hostName);
} catch (UnknownHostException ex) {
}
System.out.println("hostname: " + pduAgentAddress.getHostAddress()
+ "; port: " + nPort);
} else {
Address address = respEvnt.getPeerAddress();
String hostName = address.toString().split("/")[0];
int nPort = Integer.parseInt(address.toString().split("/")[1]);
try {
pduAgentAddress = InetAddress.getByName(hostName);
} catch (UnknownHostException ex) {
}
System.out.println("hostname: " + pduAgentAddress.getHostAddress()
+ "; port: " + nPort);
}
}
public static void main(String[] args) {
MultiThreadedTrapReceiver trap = new MultiThreadedTrapReceiver();
}
}
I have changed in SnmpUtilSendTrapV3 class,
.use TcpAddress targetAddress instead of Address targetAddress
use targetAddress = new TcpAddress(Inet4Address.getLocalHost(),
162); instead of targetAddress =
GenericAddress.parse("127.0.0.1/164");
TransportMapping transport = new DefaultTcpTransportMapping();
instead of TransportMapping transport = new
DefaultUdpTransportMapping();
after this implementation error is solved but , after sending pdu using snmp.send(pdu, target) everytime ResponseEvent have null value.
Anyone have a solution of this problem ,please help me
I am using the following code to connect with java socket from an Applet client. I store Client's IP Address and some random number in every NEW connection happening in addNewClient() function in the below code. I store this info in HashMap. I add more client info in the ArrayList of this HashMap.
If there is already some client info in ArrayList, I need to read through it. I am trying that in SocketConnection class below using Iterator.
The problem I see is, I am adding some 3 client info into the ArrayList. But, when i read through it using Iterator, it can get only last added Client info, and other KEYS are just getting empty. But, at the same time, its giving the ArrayList size correctly as 3
Could some experts please refer my below complete code, and advise me what could be the problem in there?
public class DataSharingSocketListner {
public static void main(String[] args) {
System.out.println("client trying to connect before thread creation");
Thread thr = new Thread(new SocketThread());
thr.start();
}
}
class SocketThread implements Runnable {
HashMap<String, ClientInfo> clientInfo = new HashMap<String, ClientInfo>();
ArrayList<HashMap<String, ClientInfo>> myList = new ArrayList<HashMap<String, ClientInfo>>();
#Override
public void run() {
try {
System.out.println("client trying to connect after thread creation");
ServerSocket server = new ServerSocket(8080);
while (true) {
SocketConnection client = new SocketConnection(server.accept(), clientInfo, myList);
client.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SocketConnection extends Thread {
InputStream input;
PrintWriter output;
Socket socket;
ObjectOutputStream out = null;
OutputStream clientOutput;
Scanner scannerObj;
HashMap<String, byte[]> hm;
InetAddress addr;
HashMap<String, ClientInfo> clientinfo;
ArrayList<HashMap<String, ClientInfo>> clientList;
public SocketConnection(Socket socket, HashMap<String, ClientInfo> clientInfo, ArrayList<HashMap<String, ClientInfo>> myList) {
super("Thread 1");
this.socket = socket;
//this.hm = dataHashMap;
this.clientinfo = clientInfo;
this.clientList = myList;
try {
// IT IS PRINTING TOTAL SIZE 3 SUCCESSFULLY HERE
int totalClientList = clientList.size();
System.out.println("totalClientList: " + totalClientList);
if ( totalClientList>0 )
{
for (int i=0; i<totalClientList; i++)
{
System.out.println("client list reading " + i);
HashMap<String, ClientInfo> tmpData = (HashMap<String, ClientInfo>) clientList.get(i);
// IT IS GETTING ONLY THE LAST KEY, OTHER KEYS ARE SHOWING EMPTY
Set<String> key = tmpData.keySet();
Iterator it = key.iterator();
while (it.hasNext()) {
System.out.println("hasNexthasNext");
String hmKey = (String)it.next();
ClientInfo hmData = (ClientInfo) tmpData.get(hmKey);
System.out.println("Key: "+hmKey +" & Data: "+hmData.getRandomNo());
it.remove(); // avoids a ConcurrentModificationException
}
}
// TO ADD NEW CLIENT EVERY TIME
addNewClient();
}
else {
System.out.println("Client List shows empty");
// TO ADD NEW CLIENT EVERY TIME
addNewClient();
}
// Not used yet, will be used
input = socket.getInputStream();
scannerObj = new Scanner(socket.getInputStream());
clientOutput = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
public int genRandomNumber() {
Random r = new Random( System.currentTimeMillis() );
return 10000 + r.nextInt(20000);
}
String getLocalIP () {
InetAddress inetAddress = null;
String ipAddress = null;
try {
inetAddress = InetAddress.getLocalHost();
ipAddress = inetAddress.getHostAddress();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("ipAddress : " + ipAddress);
return ipAddress;
}
void addNewClient () {
String ipAddress = getLocalIP();
if ( ipAddress!=null )
{
ClientInfo clientobj = new ClientInfo();
clientobj.setIPAdd(ipAddress);
int randno = genRandomNumber();
System.out.println("genRandomNumber() : " + randno);
clientobj.setRandomNo(randno);
String key = String.valueOf(randno);
clientinfo.put(key, clientobj);
clientList.add(clientinfo);
}
}
#Override
public void run() {
System.out.println("Going to Read client data");
//do something
{
String hostIP = addr.getHostAddress() ;
System.out.println("hostIP: " + hostIP);
//do something
}
}
}
class ClientInfo {
private String IPAddress;
private long RandomNumber;
private byte[] data;
public static void main(String []args) {
System.out.println("Client info Main");
}
//Setter
void setIPAdd (String ip) {
System.out.println("setIPAdd called");
IPAddress = ip;
}
void setRandomNo (long randomno) {
RandomNumber = randomno;
}
void setImageData (byte[] imgData) {
data = imgData;
}
//Getter
String getIPAdd () {
return IPAddress;
}
long getRandomNo () {
return RandomNumber;
}
byte[] getImageData () {
return data;
}
}
UPDATE: As per Amrish suggestion, changed the following code, it solved the issue.
int totalClientList = clientList.size();
System.out.println("totalClientList: " + totalClientList);
if ( totalClientList>0 )
{
for (int i=0; i<totalClientList; i++)
{
System.out.println("client list reading " + i);
HashMap<String, ClientInfo> tmpData = (HashMap<String, ClientInfo>) clientList.get(i);
Set<String> key = tmpData.keySet();
System.out.println("key: " + key);
}
addNewClient();
}
else {
System.out.println("Client List shows empty");
addNewClient();
}
void addNewClient () {
String ipAddress = getLocalIP();
if ( ipAddress!=null )
{
// CREATE NEW OBJECT EVERY TIME WHEN STORING
HashMap<String, ClientInfo> clientInfo = new HashMap<String, ClientInfo>();
ClientInfo clientobj = new ClientInfo();
//System.out.println("Test log 1" + clientobj);
clientobj.setIPAdd(ipAddress);
// System.out.println("Test log 2");
int randno = genRandomNumber();
System.out.println("genRandomNumber() : " + randno);
clientobj.setRandomNo(randno);
String key = String.valueOf(randno);
//System.out.println("key: " + key);
clientInfo.put(key, clientobj);
clientList.add(clientInfo);
}
}
Your Arraylist has 3 hashmap but each hashmap has only one object. Hence , you are getting size as 3 but only one object is returned when you iterate over the hashmap.
Problem here is you are comparing two different things:
int totalClientList = clientList.size();
this will give you the number of clients you have in your list:
HashMap<String, ClientInfo> tmpData = (HashMap<String, ClientInfo>) clientList.get(i);
Set<String> key = tmpData.keySet();
This will give you the keys of the i'th client. which is different than the total clients.
What you should do is to drop List of hashmaps and just use a single HashMap to keep track of all the clients.
Hope this helps.
Change your SocketThread to remove list
class SocketThread implements Runnable {
HashMap<String, ClientInfo> clientInfo = new HashMap<String, ClientInfo>();
#Override
public void run() {
try {
System.out.println("client trying to connect after thread creation");
ServerSocket server = new ServerSocket(8080);
while (true) {
SocketConnection client = new SocketConnection(server.accept(), clientInfo);
client.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
change your SockectConnection to remove list
HashMap<String, ClientInfo> clientinfo;
public SocketConnection(Socket socket, HashMap<String, ClientInfo> clientInfo) {
super("Thread 1");
this.socket = socket;
//this.hm = dataHashMap;
this.clientinfo = clientInfo;
try {
// IT IS PRINTING TOTAL SIZE 3 SUCCESSFULLY HERE
int totalClientList = clientInfo.size();
System.out.println("totalClientList: " + totalClientList);
if ( totalClientList>0 )
{
// IT IS GETTING ONLY THE LAST KEY, OTHER KEYS ARE SHOWING EMPTY
Set<String> key = clientInfo.keySet()
Iterator it = key.iterator();
while (it.hasNext()) {
System.out.println("hasNexthasNext");
String hmKey = (String)it.next();
ClientInfo hmData = (ClientInfo) tmpData.get(hmKey);
System.out.println("Key: "+hmKey +" & Data: "+hmData.getRandomNo());
it.remove(); // avoids a ConcurrentModificationException
}
// TO ADD NEW CLIENT EVERY TIME
addNewClient();
}
else {
System.out.println("Client List shows empty");
// TO ADD NEW CLIENT EVERY TIME
addNewClient();
}
// Not used yet, will be used
input = socket.getInputStream();
scannerObj = new Scanner(socket.getInputStream());
clientOutput = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
Change Add New Client:
void addNewClient () {
String ipAddress = getLocalIP();
if ( ipAddress!=null )
{
ClientInfo clientobj = new ClientInfo();
clientobj.setIPAdd(ipAddress);
int randno = genRandomNumber();
System.out.println("genRandomNumber() : " + randno);
clientobj.setRandomNo(randno);
String key = String.valueOf(randno);
clientinfo.put(key, clientobj);
}
}
I just edited your code, it should give you a start. Hope this helps.
You are talking about two different things. One is the size of a list, the other one is the size of a hashMap.
Try this:
int mapSize = tmpData.size();
You can get the size of the map and check if it's right.