message to specific client using multi threaded server - java

I have a multi threaded server in which server is waiting for all possible clients to be connected.As soon as client is connected it sends an int(12345) to server and server reads and display it now server uses a specific IPaddress of a client using hash map architecture sends a message to that client to which ipaddress is matched.but my code is stuck in while loop and it isn't go to the function messagetospecificclient() and if it goes it displays null. Sorry for my bad English
My code is
Server
public class ServerStart implements Runnable
{
#Override
public void run()
{
try
{
HandleMultipleClients hmc=new HandleMultipleClients();
hmc.connect();
hmc.messagetospecificclients("172.20.3.122");
}
}
HandleMultipleClients
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package zeeshannisar210;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
*
* #author Zeeshan Nisar
*/
public class HandleMultipleClients{
Map<Integer, java.net.Socket> clients = new HashMap<Integer, java.net.Socket> ();
Socket sock;
ServerSocket serverSock;
DataOutputStream dos;
DataInputStream dis;
String ip;
public HandleMultipleClients()
{
}
public void connect()
{
try
{
serverSock = new ServerSocket(2101);
while (true)
{
sock = serverSock.accept();
clients.put(sock.getPort(), sock);
dis=new DataInputStream(sock.getInputStream());
int s=dis.readInt();
System.out.print(s);
messagetospecificclients(ip);
}
}
catch(Exception e)
{
}
}
public void messagetospecificclients(String ipaddress) throws IOException
{
System.out.print(ipaddress);
for (Iterator<Integer> iter = clients.keySet().iterator(); iter.hasNext(); )
{
int key = iter.next();
System.out.print("ok1");
ip=ipaddress;
System.out.print(ip);
System.out.print("ok2");
java.net.Socket client = clients.get(key);
InetAddress zee = client.getInetAddress();
String s = zee.getHostAddress();
System.out.print("ok3");
System.out.print(s);
if (s.equals(ipaddress))
{
System.out.print("ok4");
dos =new DataOutputStream(client.getOutputStream());
dos.writeUTF("Some message");
}
}
}
public static void main(String[] args) {
new HandleMultipleClients();
}
}
Client code is
public class messagefromserver implements Runnable
{
#Override
public void run()
{
try
{
sock = new Socket("localhost",2101);
System.out.println("Success");
dos=new DataOutputStream(sock.getOutputStream());
dos.writeInt(12345);
// Basicinfosend bis=new Basicinfosend(sock);
// Thread t1=new Thread(bis);
// t1.start();
// Thread.sleep(1000);
// Systeminfosend sis=new Systeminfosend(sock);
// Thread t2=new Thread(sis);
// t2.start();
// Thread.sleep(1000);
// Thread p = new Thread(new Process());
// p.start();
while(true)
{
String s=dis.readUTF();
System.out.print(s);
}
}

Related

Java multi-threading Concurrency vs Parallelism

Hi programmer all over the world
In order to understand what's the difference between Concurrency vs Parallelism, I was given this problem to solve but I fall off in this problem that I couldn't solve and it took me a lot of time , so I came here and I home someone could help me .
I have a problemm here I have built a program that has 4 classes , 2 of them are "Client" (Agsrq to send generates squares numbers and AgFibo so send sequence of number of fibonacci) used to send number to the server (agclassserver recieve data from Agsqr and Agfibo to order and display them in form of list ) , and I add other class to make server accepts many clients (Multithreading) in this case ,Agsqr and AgFibo are taking the role of client.
So here is my problem , when I execute the classes (agclassserver "server" , Agsqr & AgFibo "Clients") the result is giving me only the fist client lets say "Agsqr" and when I execute the AgFibo it doesn't executes but it gives me another execution of Agsqr "so I have the result of two Agsqr "
Here is all the class I vae used in this program
Agclassserver
package smatp2;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.*;
public class agclassserver {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ArrayList<Integer> array = new ArrayList<Integer>();
ArrayList<ClassesHandler> classes_handler = new ArrayList<ClassesHandler>();
ExecutorService service= Executors.newFixedThreadPool(10);
boolean var=true;
int message;
try {
while(true) {
ServerSocket server = new ServerSocket(9090);
System.out.println("I waiting for the client ");
Socket socket = server.accept();// waiting for client to connect with server
ClassesHandler client = new ClassesHandler(socket);
classes_handler.add(client);
service.execute(client);
}
}catch (Exception e) {
}
}
}
Agsqr
package smatp2;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Agsqr {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
try {
Socket socket = new Socket ("localhost", 9090);
int n=0;
OutputStream output = socket.getOutputStream();
DataOutputStream stream = new DataOutputStream(output);
while(true) {
int result = n*n;
stream.writeInt(result);
n++;
Thread.sleep(1000);
}
}catch(Exception e) {
}
}
}
AgFibo
package smatp2;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class AgFibo extends Thread {
public synchronized void run() {
}
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
// TODO Auto-generated method stub
try {
int number ;
int previousNumber = 0;
int nextNumber = 1;
boolean variable=false ;
Socket socket = new Socket ("localhost", 9090);
int n=0;
OutputStream output = socket.getOutputStream();
DataOutputStream stream = new DataOutputStream(output);
while(!variable){
stream.writeInt(previousNumber);
int sum = previousNumber + nextNumber;
previousNumber = nextNumber;
nextNumber = sum;
Thread.sleep(1000);
}
}catch(Exception e) {
}
}
}
ClassesHandler
package smatp2;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
public class ClassesHandler implements Runnable {
private Socket socket;
private int message;
ArrayList<Integer> array = new ArrayList<Integer>();
private DataInputStream dataInputStream;
public ClassesHandler(Socket socket) throws IOException{
this.socket = socket;
dataInputStream = new DataInputStream(socket.getInputStream());
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
while(true) {
message = dataInputStream.readInt();
array.add(message);// waiting for client to connect with server
Collections.sort(array);
System.out.println(message);
System.out.println(array);
//Thread.sleep(500);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
agclassserver /* Sorry I forgot to post the classserver Class */
package smatp2;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.*;
public class agclassserver {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ArrayList<Integer> array = new ArrayList<Integer>();
ArrayList<Integer> arraySQR = new ArrayList<Integer>();
ArrayList<Integer> arrayFibo = new ArrayList<Integer>();
ArrayList<ClassesHandler> classes_handler = new ArrayList<ClassesHandler>();
ExecutorService service= Executors.newFixedThreadPool(10);
boolean var=true;
int message;
try {
ServerSocket server = new ServerSocket(9090);
while(true) {
System.out.println("I waiting for the client ");
Socket socket = server.accept();// waiting for client to connect with server
String hostName = socket.getInetAddress().getHostName();
ClassesHandler client = new ClassesHandler(socket,array,arraySQR,arrayFibo,hostName);
classes_handler.add(client);
service.execute(client);
}
}catch (Exception e) {
}
}
}
Concurrent vs Parallel.
Imagine you need to get a new passport and you need to prepare a presentation for work.
Not parallel and not concurrent: first you go get your passport and then you prepare a presentation.
Not parallel, but concurrent: you go to the embassy and wait on a chair for you turn. While you are waiting, you work on your presentation. As soon as it is your turn, you close your laptop and fill in the passport papers and later you will complete your presentation.
Parallel and concurrent: you go work on your presentation while you send your wife/husband to the embassy to get your passport.
There is also a possibility to do parallel and not concurrent. But that doesn't fit with the above example. And example would calculating the sum of 2 huge integer arrays. Using SIMD multiple integer adds can be executed in parallel, but there is no concurrency since there is just a single request.

Current thread itself waiting infinitely while trying to call wait() on another thread

I am trying to make another thread wait in below code but my current thread itself is waiting infinitely.
Below are two java classes Server.java that spawns runnable instances of ServerService.java.
When such running instance of "ServerService.java" call enqueue method of Server.java.Server.java should make such callee thread wait. But seems my Server.java Thread itself waits infinitely
Server.java
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server{
private ServerSocket server=null;
public static Map<Socket,String> clientsConnected=null;
public static Map<Socket,Runnable> clientsAndThreads=null;
public static ExecutorService executor=null;
public static List<Runnable> requestQueue=null;
public static Map<Runnable,Integer> threadAndRespectiveTime=null;
/*
* Contructor
*/
Server(){
clientsConnected=new HashMap<Socket,String>();
clientsAndThreads=new HashMap<Socket,Runnable>();
threadAndRespectiveTime=new HashMap<>();
requestQueue=new ArrayList<>();
}
/*
* Accepts connections from clients continually till the server is UP(max 10 clients)
*/
public void acceptConnection(){
try{
executor=Executors.newFixedThreadPool(10);
new Thread(new Runnable() {
#Override
public void run() {
Socket client=null;
while(server.isBound()){
try{
client=server.accept();
DataInputStream di= new DataInputStream(client.getInputStream());
String msg=di.readUTF();
clientsConnected.put(client, getMessage(msg));
ServerWindow.write(msg);
Runnable service= new ServerService(client,getMessage(msg));
executor.execute(service);
clientsAndThreads.put(client, service);
}catch(Exception e){
System.err.println("error occurred while accepting connections");
}
}
}
}).start();
System.out.println("now dequeuing");
while(true){
dequeue();
}
}catch(Exception e){
System.err.println("Server:error while accepting connections"+e.getMessage());
}
}
public static void enqueue(Socket clientSocket,Integer secondsToWait){
try{
Runnable respectiveThread = clientsAndThreads.get(clientSocket);
threadAndRespectiveTime.put(respectiveThread, secondsToWait);
System.out.println("making thread wait");
synchronized (respectiveThread) {
respectiveThread.wait();
}
requestQueue.add(respectiveThread);
System.out.println("done enqueuing");
}catch(Exception e){
e.printStackTrace();
}
}
public static void dequeue() throws InterruptedException{
while(!requestQueue.isEmpty()){
Runnable currentThread=requestQueue.get(0);
Integer timeToWait=threadAndRespectiveTime.get(currentThread);
Thread.sleep(timeToWait * 1000);
requestQueue.remove(0);
System.out.println("wait is complete now notifying thread");
synchronized (currentThread) {
currentThread.notify();
}
}
}
/*
* This method takes out actual message from http format
*/
public String getMessage(String str){
return str.substring(str.indexOf("message:")+8, str.length());
}
/*
* Starts the server listening to port 4000
*/
public void start_server(){
try{
if(server==null || !server.isBound()){
server = new ServerSocket(4000);
}
acceptConnection();
}catch(Exception e){
System.err.println("Server:error occurred while server start"+e.getMessage());
}
}
/*
* Closes client sockets of every connected client, shuts down the thread executor that serves clients
*/
public void stop_server() throws IOException{
Iterator it=clientsConnected.entrySet().iterator();
while(it.hasNext()){
Map.Entry e= (Map.Entry)it.next();
Socket toBeClosed=(Socket)e.getKey();
toBeClosed.close();
}
executor.shutdownNow();
server.close();
}
}
Below is the class which is spawn as thread by Server.java
ServerService.java
`import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;
/*
* This class serves the client
*/
public class ServerService extends Server implements Runnable{
private Socket client=null;
private String clientBeingServed=null;
private DataOutputStream dout=null;
private DataInputStream din=null;
/*
* This is construcor that takes client sockte that already has been connected to server and client name.
* It initializes and input and output streams for serving the respective client
*/
public ServerService(Socket client,String name) throws IOException {
this.client=client;
this.clientBeingServed=name;
dout=new DataOutputStream(client.getOutputStream());
din=new DataInputStream(client.getInputStream());
}
/*
* takes out actual message sent by client from its http format
*/
public String getMessage(String str){
//System.out.println("returning\n"+str.substring(str.indexOf("message:")+8, str.length()));
return str.substring(str.indexOf("message:")+8, str.length());
}
/*
* This method converts a message string into HTTP formatted string
*/
public String getHttpMessage(String msg){
String str="POST Http/1.1 \n" + "Host: www.uta.com \n" + "User-Agent: Mozilla/5.0 \n"
+ "Content=type: application/x-www-form-urlencoded \n" + "Content-Length: " + msg.length() + " \n"
+ "Date:" + new Date() + " \n" + "message:" + msg;
return str;
}
/*
* This method execute when thread for this class is executed from Server.java file after connection is accepted
*/
#Override
public void run() {
int waitTime=0;
try{
while(client.isConnected()){
String msg=din.readUTF();
ServerWindow.write(msg);
waitTime=Integer.parseInt(getMessage(msg));
System.out.println("Equeing:"+clientBeingServed);
Server.enqueue(client, waitTime);
ServerWindow.write("Served client:"+clientBeingServed);
dout.writeUTF(getHttpMessage("Server waited "+waitTime+" seconds for "+clientBeingServed));
dout.flush();
}
client.close();
}catch(Exception e){
System.err.println("ServerService:error serving client"+clientBeingServed+e.getMessage());
}
}
}`
Instead of calling wait on spawned thread, My ServerService thread instance waits itself after calling enqueue method of Server.java.
Then later Server.java calls notify to resume ServerService thread.
Server.java
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
public class Server{
private ServerSocket server=null;
public static Map<Socket,String> clientsConnected=null;
public static Map<Socket,Runnable> clientsAndThreads=null;
public static ExecutorService executor=null;
public static Queue<Thread> requestQueue=null;
public static Map<Thread,Integer> threadAndRespectiveTime=null;
/*
* Contructor
*/
Server(){
clientsConnected=new HashMap<Socket,String>();
clientsAndThreads=new HashMap<Socket,Runnable>();
threadAndRespectiveTime=new HashMap<>();
requestQueue=new LinkedList<>();
}
/*
* Accepts connections from clients continually till the server is UP(max 10 clients)
*/
public void acceptConnection(){
try{
executor=Executors.newFixedThreadPool(10);
new Thread(new Runnable() {
#Override
public void run() {
Socket client=null;
while(server.isBound()){
try{
client=server.accept();
DataInputStream di= new DataInputStream(client.getInputStream());
String msg=di.readUTF();
clientsConnected.put(client, getMessage(msg));
ServerWindow.write(msg);
Runnable service= new ServerService(client,getMessage(msg));
executor.execute(service);
}catch(Exception e){
System.err.println("error occurred while accepting connections");
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
while(true){
Server.dequeue();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}catch(Exception e){
System.err.println("Server:error while accepting connections"+e.getMessage());
}
}
public static synchronized void enqueue(Thread t,Integer secondsToWait){
try{
System.out.println(requestQueue );
threadAndRespectiveTime.put(t, secondsToWait);
requestQueue.add(t);
}catch(Exception e){
e.printStackTrace();
}
}
public static synchronized void dequeue() throws InterruptedException{
while(!requestQueue.isEmpty()){
Thread currentThread=requestQueue.remove();
Integer timeToWait=threadAndRespectiveTime.get(currentThread);
System.out.println("time to wait is:"+timeToWait);
Thread.currentThread().sleep(timeToWait * 1000);
synchronized (currentThread) {
currentThread.notify();
}
}
}
/*
* This method takes out actual message from http format
*/
public String getMessage(String str){
return str.substring(str.indexOf("message:")+8, str.length());
}
/*
* Starts the server listening to port 4000
*/
public void start_server(){
try{
if(server==null || !server.isBound()){
server = new ServerSocket(4000);
}
acceptConnection();
}catch(Exception e){
System.err.println("Server:error occurred while server start"+e.getMessage());
}
}
/*
* Closes client sockets of every connected client, shuts down the thread executor that serves clients
*/
public void stop_server() throws IOException{
Iterator it=clientsConnected.entrySet().iterator();
while(it.hasNext()){
Map.Entry e= (Map.Entry)it.next();
Socket toBeClosed=(Socket)e.getKey();
toBeClosed.close();
}
executor.shutdownNow();
server.close();
}
}
ServerService.java
==================
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;
/*
* This class serves the client
*/
public class ServerService extends Server implements Runnable{
private Socket client=null;
private String clientBeingServed=null;
private DataOutputStream dout=null;
private DataInputStream din=null;
/*
* This is construcor that takes client sockte that already has been connected to server and client name.
* It initializes and input and output streams for serving the respective client
*/
public ServerService(Socket client,String name) throws IOException {
this.client=client;
this.clientBeingServed=name;
dout=new DataOutputStream(client.getOutputStream());
din=new DataInputStream(client.getInputStream());
}
/*
* takes out actual message sent by client from its http format
*/
public String getMessage(String str){
//System.out.println("returning\n"+str.substring(str.indexOf("message:")+8, str.length()));
return str.substring(str.indexOf("message:")+8, str.length());
}
/*
* This method converts a message string into HTTP formatted string
*/
public String getHttpMessage(String msg){
String str="POST Http/1.1 \n" + "Host: www.uta.com \n" + "User-Agent: Mozilla/5.0 \n"
+ "Content=type: application/x-www-form-urlencoded \n" + "Content-Length: " + msg.length() + " \n"
+ "Date:" + new Date() + " \n" + "message:" + msg;
return str;
}
/*
* This method execute when thread for this class is executed from Server.java file after connection is accepted
*/
#Override
public void run() {
int waitTime=0;
try{
while(client.isConnected()){
String msg=din.readUTF();
ServerWindow.write(msg);
waitTime=Integer.parseInt(getMessage(msg));
System.out.println("Equeing:"+clientBeingServed);
Server.enqueue(Thread.currentThread(), waitTime);
System.out.println("before going to sleep");
synchronized (Thread.currentThread()) {
Thread.currentThread().wait();
}
System.out.println("after sleeping");
ServerWindow.write("Served client:"+clientBeingServed);
dout.writeUTF(getHttpMessage("Server waited "+waitTime+" seconds for "+clientBeingServed));
dout.flush();
}
client.close();
}catch(Exception e){
System.err.println("ServerService:error serving client"+clientBeingServed+e.getMessage());
}
}
}

How can I get this abstract class to send its output to a socket?

I'm experimenting with creating a socket application that sends some data from another application to a client. The code to access the data uses an abstract class.
SubscriptionAdapter listener = new SubscriptionAdapter() {
#Override
public void onSubscriptionData(SubscriptionData data) {
for (AnyJson json : data.getMessages()) {
System.out.println(json.toString());
}
}
};
The mechanics of SubscriptionAdapter() were a little weird to figure out. onSubscriptionData gets called over and over and the for loop will return 1 to many records. Here is some sample output:
Yup
Got message: {"type":"lightning","location":{"coords":{"lon":18.509391,"lat":38.7581},"polarity":0}}
Yup
Got message: {"type":"lightning","location":{"coords":{"lon":18.504115,"lat":38.765076},"polarity":0}}
Got message: {"type":"lightning","location":{"coords":{"lon":18.494549,"lat":38.778813},"polarity":0}}
"Yup" is a line of debug code I put in above the for loop to confirm how the class functions.
Below is the sample socket server I'm working with:
import java.net.*;
import java.io.*;
public class Server {
/**
* #param args the command line arguments
*/
public static void main(String[] args) //throws Exception
{
try
{
ServerSocket serverSocket = new ServerSocket(9090);
System.out.println("Waiting for clients...");
Socket socket = serverSocket.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("Hello client!");
out.close();
socket.close();
serverSocket.close();
} catch (Exception e)
{
System.out.println(e.toString());
}
}
}
The goal is to get System.out.println(json.toString()); to output to the socket connection. However, I've been running into scope issues.
I can't just put the code for the server inside onSubscriptionData because it will keep trying to create a new socket on a port that is already open.
I can't put the code OUTSIDE of the abstract class because then PrintWriter out = new PrintWriter(socket.getOutputStream(), true); winds up being out of scope.
I've been at it for a few hours and at this point, I could use some suggestions.
Update as requested. Below is the full code:
import com.satori.rtm.*;
import com.satori.rtm.model.*;
public class SubscribeToWeatherChannel {
static final String endpoint = [end point];
static final String appkey = [app key];
static final String channel = "full-weather";
public static void main(String[] args) throws InterruptedException {
final RtmClient client = new RtmClientBuilder(endpoint, appkey)
.setListener(new RtmClientAdapter() {
#Override
public void onEnterConnected(RtmClient client) {
System.out.println("Connected to Satori RTM!");
}
})
.build();
SubscriptionAdapter listener = new SubscriptionAdapter() {
#Override
public void onSubscriptionData(SubscriptionData data) {
for (AnyJson json : data.getMessages()) {
System.out.println(json.toString());
}
}
};
client.createSubscription(channel, SubscriptionMode.SIMPLE, listener);
client.start();
}
}
Credit actually to Kayaman for the solution.
Don't create an anonymous instance of the abstract class. Create a
proper class that extends SubscriptionAdapter, then you can pass it
PrintWriters or any other things you need.
import com.satori.rtm.*;
import com.satori.rtm.model.*;
import java.net.*;
import java.io.*;
public class SpecificSubscriptionAdapter extends SubscriptionAdapter {
public static PrintWriter out;
public SpecificSubscriptionAdapter(PrintWriter out){
this.out = out;
}
#Override
public void onSubscriptionData(SubscriptionData data) {
for (AnyJson json : data.getMessages()) {
out.println(json.toString());
}
}
}

How can I make this code wait until a Thread is available in the Thread Pool?

I wanted to practice a little on Network Programming and Thread Pools with Java. Here is a sample code I written:
/* User: koray#tugay.biz Date: 21/02/15 Time: 13:30 */
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class MyServer {
static List<ServerSocketThread> myThreadPool = new ArrayList<ServerSocketThread>();
static int numberOfCurrentConnections = 0;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
ServerSocketThread threadOne = new ServerSocketThread(null);
ServerSocketThread threadTwo = new ServerSocketThread(null);
myThreadPool.add(threadOne);
myThreadPool.add(threadTwo);
while (true) {
if(numberOfCurrentConnections < 2) {
Socket accept = serverSocket.accept();
ServerSocketThread thread = myThreadPool.get(numberOfCurrentConnections);
thread.setSocket(accept);
thread.start();
numberOfCurrentConnections++;
} else {
// I want to force the client to wait until a new Thread is available from the pool.
}
}
}
public static void informFinished() {
numberOfCurrentConnections--;
}
}
and the ServerSocketThread class is as follows:
/* User: koray#tugay.biz Date: 21/02/15 Time: 18:14 */
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class ServerSocketThread extends Thread {
Socket socket;
public ServerSocketThread(Socket accept) {
this.socket = accept;
}
#Override
public void run() {
try {
Scanner scanner = new Scanner(socket.getInputStream());
String readLine;
while (!(readLine = scanner.nextLine()).equals("bye")) {
System.out.println(readLine);
}
new PrintWriter(socket.getOutputStream()).write("Bye then..");
socket.close();
MyServer.informFinished();
} catch (IOException e) {
e.printStackTrace();
}
}
public void setSocket(Socket socket) {
this.socket = socket;
}
}
Well I can connect to my server with 2 different terminals like this just fine:
Korays-MacBook-Pro:~ koraytugay$ telnet localhost 8888
Trying ::1...
Connected to localhost.
Escape character is '^]'.
laylay
bombom
And the 3rd connection (if made) will not be served as there are 2 Threads only in the Thread Pool. But I can not find a way to make the 3rd client wait until a client says "bye". What I want to do is, after one of the 2 first connected clients disconnect, a Thread is allocated to the waiting 3rd Client, but how?
I will answer my own question, I made it work like this:
/* User: koray#tugay.biz Date: 21/02/15 Time: 21:12 */
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Stack;
public class MyConnectionAccepter {
private Stack<MySocketThread> mySocketThreads = new Stack<MySocketThread>();
private volatile int currentNumberOfConnections = 0;
public MyConnectionAccepter() {
MySocketThread mySocketThreadOne = new MySocketThread(this);
MySocketThread mySocketThreadTwo = new MySocketThread(this);
mySocketThreadOne.setDaemon(true);
mySocketThreadTwo.setDaemon(true);
mySocketThreadOne.start();
mySocketThreadTwo.start();
mySocketThreads.push(mySocketThreadOne);
mySocketThreads.push(mySocketThreadTwo);
}
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (true) {
while (currentNumberOfConnections < 2) {
System.out.println("Blocking now:");
Socket accept = serverSocket.accept();
System.out.println("Connection accepted..");
MySocketThread mySocketThread = mySocketThreads.pop();
mySocketThread.setSocket(accept);
System.out.println("Incrementing connections..");
currentNumberOfConnections++;
System.out.println("End of while..");
}
}
}
public void informIAmDone(MySocketThread mySocketThread) {
mySocketThreads.push(mySocketThread);
currentNumberOfConnections--;
}
}
and
/* User: koray#tugay.biz Date: 21/02/15 Time: 21:04 */
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class MySocketThread extends Thread {
private volatile Socket socket;
MyConnectionAccepter myConnectionAccepter;
public MySocketThread(MyConnectionAccepter myConnectionAccepter) {
this.myConnectionAccepter = myConnectionAccepter;
}
#Override
public synchronized void run() {
System.out.println("Started...");
serve();
}
public void setSocket(Socket socket) {
this.socket = socket;
System.out.println("Socket not null anymore..");
}
public void serve() {
while(socket == null) {
}
while (socket != null) {
Scanner scanner = null;
try {
scanner = new Scanner(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
String readLine;
while (!(readLine = scanner.nextLine()).equals("bye")) {
System.out.println(readLine);
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket = null;
myConnectionAccepter.informIAmDone(this);
}
serve();
}
}
and the Test Class:
/* User: koray#tugay.biz Date: 21/02/15 Time: 21:18 */
import java.io.IOException;
public class MyTestClass {
public static void main(String[] args) throws IOException {
MyConnectionAccepter myConnectionAccepter = new MyConnectionAccepter();
myConnectionAccepter.start();
}
}
I would suggest that you should create a threadpool as described in this article: http://tutorials.jenkov.com/java-concurrency/thread-pools.html
So basically in addition to the pool of threads you also maintain a queue of tasks. Each thread in the pool is continuously polling the task queue for tasks. Whenever a task is available (queue is not empty), it is picked up by a thread and executed. In your case the task would be handling the client connection. The the number of threads in the pool is limited ( 2 in this case). So at any time number of connections that can be processed simultaneously is 2. Only when one of two threads is done executing the current task will it pick the next one. Each time you receive a new connection request, you add a new task to the queue.
Hope this helps!

Selector.select() does not block

Sorry, I searched around for 2 days before I had to post this question. There are similar questions, but none of them helped me.
I am trying to create a simple chat application where the client uses (non-NIO) Socket to connect to the server that listens with a NIO ServerSocketChannel. The server uses a Selector. Until the first client connects, the Selector.select() method is blocked, as expected. But after the first client connects, Selector.select() does not block and returns immediately. This causes my while loop to run continuously.
Sorry, I've pasted the entire code so that you can copy-paste it and run it. I've just started with Java, so any help/pointers will be very much appreciated. Thank you.
P.S.: Right now, the client sends serialized object (Message object) over the socket connection and the Server reads it. Since the connection is non-blocking, the serialized object is pre-fixed with the object size (in bytes) before it is sent to the server. This allows the server to read the next "x" bytes and un-serialize into a Message object. The server code is a work in progress.
CLIENT CODE----------
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
public class ChatClient {
void go(){
User u = new User();
u.setName("UserA");
try{
u.setInet(InetAddress.getLocalHost());
}catch (UnknownHostException ex){
System.out.println(ex);
return;
}
Message m = new Message();
m.setType(3);
m.setText("This is the 1st message.");
m.setFromUser(u);
try{
Socket sock = new Socket (InetAddress.getLocalHost(), 5000);
DataOutputStream dataOut = new DataOutputStream(sock.getOutputStream());
ByteArrayOutputStream byteTemp = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream (byteTemp);
objOut.writeObject(m);
objOut.flush();
objOut.close();
byte[] byteMessage = byteTemp.toByteArray();
ByteBuffer bb = ByteBuffer.allocate(4);
bb.putInt(byteMessage.length);
byte[] size = new byte[4];
size = bb.array();
System.out.println("Object size = "+byteMessage.length); //370
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
byteOut.write(size);
byteOut.write(byteMessage);
byte[] finalMessage = byteOut.toByteArray();
dataOut.write(finalMessage,0,finalMessage.length);
dataOut.flush();
System.out.println("Flushed out");
}catch (Exception ex){
System.out.println(ex);
}
}
public static void main (String args[]){
new CopyOfChatClient().go();
}
}
SERVER CODE ---------------
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
public class CopyOfChatServer {
Object a, b;//Dummy objects for synchronization
SocketChannel clientSock=null;
Selector selector;
SelectionKey key;
void go(){
try{
a=new Object();//Dummy objects for synchronization
b=new Object();//Dummy objects for synchronization
ServerSocketChannel serverSock = ServerSocketChannel.open();
serverSock.socket().bind(new InetSocketAddress(5000));
//Note: ServerSocketChannel is blocking, but each new connection returned by accept() will be made non-blocking (see below)
selector = Selector.open();
new Thread(new SelectorThread()).start(); //Start the SelectorThread
int i=0;
while (true){
clientSock = serverSock.accept();
if (clientSock!=null){
clientSock.configureBlocking(false); //The default client socket returned by accept() is blocking. Set it to non-blocking.
synchronized (b){
selector.wakeup();
synchronized (a){
key = clientSock.register(selector, SelectionKey.OP_READ); //register new client Socket with selector
key.attach(clientSock);
}//sync(a)
}//sync(b)
i++;
}
System.out.println("Here");
}//while(true)
}catch (Exception ex){
System.out.println(ex);
}
}
class SelectorThread implements Runnable{
Set <SelectionKey> selectedKeys;
int readyChannels;
public void run(){
while (true){
try {
synchronized(a){
System.out.println("1. Selector trying to select");
readyChannels = selector.select();//Note: select() is blocking ?? Does not block. Behaves like non-blocking
System.out.println("2. Selector has selected");
}//sync a
synchronized (b){
//just wait till registration is done in main thread
}
if (readyChannels == 0) continue; //Even if select() is blocking, this check is to handle suprious wake-ups
System.out.println("readyChannels>0");
selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()){
SelectionKey key = keyIterator.next();
keyIterator.remove();//added after the first answer to my question
if (key.isReadable()){
System.out.println("3. Got incoming data");
SocketChannel tempSock = (SocketChannel)key.attachment();
ByteBuffer bb=ByteBuffer.allocate(8000);
int bytesRead=tempSock.read(bb);
System.out.println("4. Bytes read = "+bytesRead);
if (bytesRead>4){
bb.flip();
bb.rewind();
int size = bb.getInt();
System.out.println("5. Size of object = "+size);
byte[] objIn = new byte[size];
for (int i=0;i<size;i++){
objIn[i]=bb.get();
}
bb.compact();
ByteArrayInputStream bIn= new ByteArrayInputStream(objIn);
ObjectInputStream objStream= new ObjectInputStream(bIn);
Message temp1 = (Message) objStream.readObject();
System.out.println("6. Read object back");
System.out.println(temp1.getFromUser().getName());
}
}
}
selectedKeys.clear();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main (String args[]){
new CopyOfChatServer().go();
}
}
MESSAGE Class ----
import java.io.Serializable;
public class Message implements Serializable{
private int type;
private User fromUser;
private User toUser;
private String text;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public User getFromUser() {
return fromUser;
}
public void setFromUser(User fromUser) {
this.fromUser = fromUser;
}
public User getToUser() {
return toUser;
}
public void setToUser(User toUser) {
this.toUser = toUser;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
USER CLASS --------
import java.io.Serializable;
import java.net.InetAddress;
public class User implements Serializable{
private String name;
private InetAddress inet;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public InetAddress getInet() {
return inet;
}
public void setInet(InetAddress inet) {
this.inet = inet;
}
}
You must put
keyIterator.remove()
after
keyIterator.next()
The selector doesn't remove anything from selectedKeys() itself.
NB You don't need to attach the channel to the key as an attachment. You can get it from key.channel().

Categories