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.
Related
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);
}
}
I am not talking about threading or anything to make this more complicated.
Most server programs I saw are like this or while(true){...} (same concept).
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.io.DataOutputStream;
import java.io.IOException;
public class TCPServer {
ServerSocket welcomeSocket;
public TCPServer(int port) throws IOException {
welcomeSocket = new ServerSocket(port);
}
public void go() throws IOException {
// This is not a valid way to wait for a socket connection, You should
// not have a forever loop or while(true)
**for (; ;) {**
Socket connectionSocket = welcomeSocket.accept();
Scanner clientIn = new Scanner(connectionSocket.getInputStream());
DataOutputStream clientOut = new DataOutputStream(connectionSocket.getOutputStream());
String clientLine = clientIn.nextLine();
String modLine = clientLine.toUpperCase();
clientOut.writeBytes(modLine + "\n");
}
}
public static void main(String[] args){
try {
TCPServer server = new TCPServer(6789);
server.go();
}
catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
It is not looping permanently, your code blocks on line welcomeSocket.accept() until someone connects and only after that next lines are executed then it waits for a new connection on welcomeSocket.accept(). In other words it loops as many times as it needs( per each connection ).
If you just want to allow only one client to connect, remove for (; ;) statement. But it will require to restart your server every time.
The while(!finished) option might be a better solution than the "empty" for loop. When the exit event occurs, you just set finished to true.
You can run a scheduler with any number of thread in the pool
and prevent the main thread from termination. Here I've used input stream but you can do it in different ways. Here you can use multiple threads to get connections and customize the frequency of the scheduler.
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
public class MyTest {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4);
#Test
public void hello() {
final Runnable helloServer = new Runnable() {
public void run() {
// handle soket connection here
System.out.println("hadling connection");
}
};
final ScheduledFuture<?> helloHandle = scheduler.scheduleAtFixedRate(helloServer, 1000, 1000, TimeUnit.MILLISECONDS);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
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!
I am trying to implement a persistent http server in java, being new in socket programming, I am unaware of the complications.
But run function of ThreadHandler class, it stucks forever and keep waiting, but at the same time if new request comes a new connection is being made instead of using the previous connection itself (while the initial connection keep waiting for request).
Please suggest the correction
here is my server code that calls ThreadHandler for threading.
Server code
package httpServer;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
public class Server {
static int countofconnections = 0;
public static void main(String[] args) throws IOException {
int port = 14998;
ServerSocket socketServerSocket = new ServerSocket(port);
while(true) {
Socket socketClientSocket = socketServerSocket.accept();
countofconnections++;
//Runnable handler = new TinyHttpdSocketHandler(socket);
ThreadHandler threadHandler = new ThreadHandler(socketClientSocket);
Thread socketThread = new Thread(threadHandler, "Thread for " + socketClientSocket.toString());
System.out.println(" connection count is now : " + countofconnections+ " ");
socketThread.setDaemon(true);
socketThread.start();
}
}
}
ThreadHandler code:
package httpServer;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketTimeoutException;
//import java.util.ArrayList;
public class ThreadHandler implements Runnable{
Socket socketClientSocket;
//ServerSocket socketServerSocket;
ThreadHandler(Socket socketClientSocket){
this.socketClientSocket = socketClientSocket;
//this.socketServerSocket = socketServerSocket;
}
#Override
public void run(){
boolean alive = false;
try {
int count = 0;
socketClientSocket.setSoTimeout(40000);
BufferedReader inputFromClient = new BufferedReader(new InputStreamReader(socketClientSocket.getInputStream()));
DataOutputStream outputToClient = new DataOutputStream(socketClientSocket.getOutputStream());
String messegeFromClient = inputFromClient.readLine();
System.out.println(messegeFromClient);
while(messegeFromClient!=null) {
String requestString = messegeFromClient;
System.out.println("entering while loop");
//String in = inputFromClient.readLine();
while(messegeFromClient!=null && !messegeFromClient.equals("")) {
//System.out.printlnln(in);
messegeFromClient = inputFromClient.readLine();
//System.out.println(messegeFromClient);
if(messegeFromClient.startsWith("Connection:")) {
String[] connectionTimeString = messegeFromClient.split(" ");
if(connectionTimeString[1].equals("keep-alive")) {
alive = true;
//System.out.println("keep alive found");
}
}
}
count++;
System.out.println(count);
//System.out.printlnln( messegeFromClient);
String[] tokensStrings = requestString.split(" ");
if(tokensStrings[0].equals("GET")) {
String requestedFilename = tokensStrings[1];
if(requestedFilename.startsWith("/")) {
requestedFilename = requestedFilename.substring(1);
if(requestedFilename.startsWith("~")) {
requestedFilename = "/home/suman/users/"+requestedFilename.substring(1);
}
else {
requestedFilename = "/home/suman/public_html/"+requestedFilename;
}
System.out.println(requestedFilename);
}
File filetosend = new File(requestedFilename);
int filesize = (int) filetosend.length();
FileInputStream fileStream = null;
boolean fileFound = true;
try {
fileStream = new FileInputStream(requestedFilename);
} catch (Exception e) {
fileFound = false;
}
if(fileFound) {
byte[] fileinByte =new byte[filesize];
fileStream.read(fileinByte);
outputToClient.writeBytes("HTTP/1.0 200 Document Follows\r\n");
outputToClient.writeBytes("Content-Length: "+filesize+"\r\n\r\n");
outputToClient.write(fileinByte, 0, filesize);
}
else {
outputToClient.writeBytes("HTTP/1.0 404 Document NOT FOUND\r\n\r\n");
outputToClient.writeBytes("404 document not found");
}
outputToClient.flush();
if(alive) {
socketClientSocket.setKeepAlive(true);
socketClientSocket.setSoTimeout(100000);
}
else {
socketClientSocket.close();
System.out.println("closing socket");
break;
}
//socketClientSocket.setSoTimeout(5000);
}
System.out.println("waiting");
messegeFromClient=inputFromClient.readLine();
while( messegeFromClient == null ) {
//this code should be skipped when a new request is made since message from from client will no longer be null in that case
messegeFromClient=inputFromClient.readLine();
}
if(messegeFromClient==null) {
System.out.println("messege is null... I don't think it would be ever executed.");
}
}
socketClientSocket.close();
System.out.println("closing socket 2");
} catch ( SocketTimeoutException e) {
try {
socketClientSocket.close();
System.out.println("socket closed");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
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().