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.
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
I have a huge CSV file ~800 K records and using that data I have to form a POST request and make a rest call.
Initially I tried WITHOUT using threads but it is taking very long time to process it.
So I thought of using threads to speed up the process and followed below approach.
divided file into relatively smaller files (Tried with 3 files with approx ~5K data each file). (I Did this Manually Before passing to application)
Created 3 threads (traditional way by extending Thread class)
Reads each file with each thread and form HashMap with details required to form request and added it to ArrayList of POST Request
Send Post request to in loop
List item
Get the Response and add it to Response List
Both above approach takes too long to even complete half (>3 hrs). Might be one of them would not be good approach.
Could anyone please provide suggestion which helps me speeding up the process ? It is NOT mandatory to use threading.
Just to add that my code is at the consumer end and does not have much control on producer end.
MultiThreadedFileRead (Main class that Extends Thread)
class MultiThreadedFileRead extends Thread
{
public static final String EMPTY = "";
public static Logger logger = Logger.getLogger(MultiThreadedFileRead.class);
BufferedReader bReader = null;
String filename = null;
int Request_Num = 0;
HashMap<Integer, String> filteredSrcDataMap = null;
List<BrandRQ> brandRQList = null;
List<BrandRS> brandRSList = null;
ReadDLShipFile readDLShipFile = new ReadDLShipFile();
GenerateAndProcessPostBrandAPI generateAndProcessPostBrandAPI = new GenerateAndProcessPostBrandAPI();
MultiThreadedFileRead()
{
}
MultiThreadedFileRead(String fname) throws Exception
{
filename = fname;
Request_Num = 0;
List<BrandRQ> brandRQList = new ArrayList<BrandRQ>();
List<BrandRS> brandRSList = new ArrayList<BrandRS>();
this.start();
}
public void run()
{
logger.debug("File *** : " + this.filename);
//Generate Source Data Map
HashMap<Integer, String> filteredSrcDataMap = (HashMap<Integer, String>) readDLShipFile.readSourceFileData(this.filename);
generateAndProcessPostBrandAPI.generateAndProcessPostRequest(filteredSrcDataMap, this);
}
public static void main(String args[]) throws Exception
{
String environment = ""; // TO BE UNCOMMENTED
String outPutfileName = ""; // TO BE UNCOMMENTED
BrandRetrivalProperties brProps = BrandRetrivalProperties.getInstance();
if(args != null && args.length == 2 && DLPremiumUtil.isNotEmpty(args[0]) && DLPremiumUtil.isNotEmpty(args[1])) // TO BE UNCOMMENTED
{
environment = args[0].trim();
outPutfileName = args[1].trim();
ApplicationInitializer applicationInitializer = new ApplicationInitializer(environment);
applicationInitializer.initializeParams();
logger.debug("Environment : " + environment);
logger.debug("Filename : " + outPutfileName);
// TO BE UNCOMMENTED - START
}else{
System.out.println("Invalid parameters passed. Expected paramenters: Environment");
System.out.println("Sample Request: java -jar BrandRetrival.jar [prd|int] brand.dat");
System.exit(1);
}
MultiThreadedFileRead multiThreadedFileRead = new MultiThreadedFileRead();
List<String> listOfFileNames = multiThreadedFileRead.getFileNames(brProps);
logger.debug("List : " + listOfFileNames);
int totalFileSize = listOfFileNames.size();
logger.debug("totalFileSize : " + totalFileSize);
MultiThreadedFileRead fr[]=new MultiThreadedFileRead[totalFileSize];
logger.debug("Size of Array : " + fr.length);
for(int i = 0; i < totalFileSize; i++)
{
logger.debug("\nFile Getting Added to Array : " + brProps.getCountFilePath()+listOfFileNames.get(i));
fr[i]=new MultiThreadedFileRead(brProps.getCountFilePath()+listOfFileNames.get(i));
}
}
public List<String> getFileNames(BrandRetrivalProperties brProps)
{
MultiThreadedFileRead multiThreadedFileRead1 = new MultiThreadedFileRead();
BufferedReader br = null;
String line = "";
String filename = multiThreadedFileRead1.getCounterFileName(brProps.getCountFilePath(), brProps.getCountFilePathStartsWith());
List<String> fileNameList = null;
logger.debug("filename : " + filename);
if(filename != null)
{
fileNameList = new ArrayList<String>();
try{
br = new BufferedReader(new FileReader(brProps.getCountFilePath()+filename));
while ((line = br.readLine()) != null)
{
fileNameList.add(line);
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e2) {
// TODO Auto-generated catch block ;
e2.printStackTrace();
} catch (Exception e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
} finally
{
if (br != null)
{
try
{
br.close();
} catch (IOException e4)
{
e4.printStackTrace();
} catch (Exception e5)
{
e5.printStackTrace();
}
}
}
}
return fileNameList;
}
// Get the Name of the file which has name of individual CSV files to read to form the request
public String getCounterFileName(String sourceFilePath, String sourceFileNameStartsWith)
{
String fileName = null;
if(sourceFilePath != null && !sourceFilePath.equals(EMPTY) &&
sourceFileNameStartsWith != null && !sourceFileNameStartsWith.equals(EMPTY))
{
File filePath = new File(sourceFilePath);
File[] listOfFiles = filePath.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile() && listOfFiles[i].getName().startsWith(sourceFileNameStartsWith)) {
fileName = listOfFiles[i].getName();
} else if (listOfFiles[i].isDirectory()) {
fileName = null;
}
}
}
return fileName;
}
}
GenerateAndProcessPostBrandAPI
public class GenerateAndProcessPostBrandAPI {
public static Logger logger = Logger.getLogger(GenerateAndProcessPostBrandAPI.class);
List<BrandRQ> brandRQList = new ArrayList<BrandRQ>();
List<BrandRS> brandRSList = new ArrayList<BrandRS>();
DLPremiumClientPost dlPremiumclientPost = new DLPremiumClientPost();
JSONRequestGenerator jsonRequestGenerator = new JSONRequestGenerator();
public List<BrandRQ> getBrandRequstList(Map<Integer, String> filteredSrcDataMap)
{
if(filteredSrcDataMap != null)
{
brandRQList = jsonRequestGenerator.getBrandRQList(filteredSrcDataMap, brandRQList);
}
return brandRQList;
}
public void generateAndProcessPostRequest(Map<Integer, String> filteredSrcDataMap, MultiThreadedFileRead multiThreadedFileRead)
{
if(filteredSrcDataMap != null)
{
brandRQList = jsonRequestGenerator.getBrandRQList(filteredSrcDataMap, brandRQList);
if(brandRQList != null && brandRQList.size() > 0)
{
BrandRetrivalProperties brProps = BrandRetrivalProperties.getInstance();
String postBrandsEndpoint = brProps.getPostBrandsEndPoint();
for (BrandRQ brandRQ : brandRQList)
{
multiThreadedFileRead.Request_Num = multiThreadedFileRead.Request_Num + 1;
logger.debug("Brand Request - " + multiThreadedFileRead.Request_Num + " : " + ObjectToJSONCovertor.converToJSON(brandRQ));
BrandRS brandResponse = dlPremiumclientPost.loadBrandApiResponseJSON(brandRQ, postBrandsEndpoint, DLPremiumUtil.getTransactionID(), BrandConstants.AUTH_TOKEN);
logger.debug("Response - " + multiThreadedFileRead.Request_Num + " : " + ObjectToJSONCovertor.converToJSON(brandResponse));
brandRSList.add(brandResponse);
}
}
}
}
}
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 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.
In a traditional blocking-thread server, I would do something like this
class ServerSideThread {
ObjectInputStream in;
ObjectOutputStream out;
Engine engine;
public ServerSideThread(Socket socket, Engine engine) {
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
this.engine = engine;
}
public void sendMessage(Message m) {
out.writeObject(m);
}
public void run() {
while(true) {
Message m = (Message)in.readObject();
engine.queueMessage(m,this); // give the engine a message with this as a callback
}
}
}
Now, the object can be expected to be quite large. In my nio loop, I can't simply wait for the object to come through, all my other connections (with much smaller workloads) will be waiting on me.
How can I only get notified that a connection has the entire object before it tells my nio channel it's ready?
You can write the object to a ByteArrayOutputStream allowing you to give the length before an object sent. On the receiving side, read the amount of data required before attempting to decode it.
However, you are likely to find it much simpler and more efficient to use blocking IO (rather than NIO) with Object*Stream
Edit something like this
public static void send(SocketChannel socket, Serializable serializable) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for(int i=0;i<4;i++) baos.write(0);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(serializable);
oos.close();
final ByteBuffer wrap = ByteBuffer.wrap(baos.toByteArray());
wrap.putInt(0, baos.size()-4);
socket.write(wrap);
}
private final ByteBuffer lengthByteBuffer = ByteBuffer.wrap(new byte[4]);
private ByteBuffer dataByteBuffer = null;
private boolean readLength = true;
public Serializable recv(SocketChannel socket) throws IOException, ClassNotFoundException {
if (readLength) {
socket.read(lengthByteBuffer);
if (lengthByteBuffer.remaining() == 0) {
readLength = false;
dataByteBuffer = ByteBuffer.allocate(lengthByteBuffer.getInt(0));
lengthByteBuffer.clear();
}
} else {
socket.read(dataByteBuffer);
if (dataByteBuffer.remaining() == 0) {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(dataByteBuffer.array()));
final Serializable ret = (Serializable) ois.readObject();
// clean up
dataByteBuffer = null;
readLength = true;
return ret;
}
}
return null;
}
Inspired by the code above I've created a (GoogleCode project)
It includes a simple unit test:
SeriServer server = new SeriServer(6001, nthreads);
final SeriClient client[] = new SeriClient[nclients];
//write the data with multiple threads to flood the server
for (int cnt = 0; cnt < nclients; cnt++) {
final int counterVal = cnt;
client[cnt] = new SeriClient("localhost", 6001);
Thread t = new Thread(new Runnable() {
public void run() {
try {
for (int cnt2 = 0; cnt2 < nsends; cnt2++) {
String msg = "[" + counterVal + "]";
client[counterVal].send(msg);
}
} catch (IOException e) {
e.printStackTrace();
fail();
}
}
});
t.start();
}
HashMap<String, Integer> counts = new HashMap<String, Integer>();
int nullCounts = 0;
for (int cnt = 0; cnt < nsends * nclients;) {
//read the data from a vector (that the server pool automatically fills
SeriDataPackage data = server.read();
if (data == null) {
nullCounts++;
System.out.println("NULL");
continue;
}
if (counts.containsKey(data.getObject())) {
Integer c = counts.get(data.getObject());
counts.put((String) data.getObject(), c + 1);
} else {
counts.put((String) data.getObject(), 1);
}
cnt++;
System.out.println("Received: " + data.getObject());
}
// asserts the results
Collection<Integer> values = counts.values();
for (Integer value : values) {
int ivalue = value;
assertEquals(nsends, ivalue);
System.out.println(value);
}
assertEquals(counts.size(), nclients);
System.out.println(counts.size());
System.out.println("Finishing");
server.shutdown();