I can send data in python and received in server, but after sleep more than 1ms(if do some For-loops(E.g: for i in range(0, 60):
print i), the result is same), I use socket to send data, but can't be received in java server.
There are code:
A client is writen in python2:
address = ('127.0.0.1', 9898)
ccc = socket(AF_INET, SOCK_STREAM)
ccc.connect(address)
ccc.send("client" + str(1) + ":before time.sleep send1111\n")
time.sleep(0.001)
ccc.send("client2:222222 after time.sleep\n")# if sleep 0.0009,can received,but 0.001 can't
A server is written in java:
ReceiveListener listener = new ReceiveListener() {
#Override
public void onReceived(int clientId, String msg) {
System.out.println(clientId + ":" + msg);
}
};
ClientManager clientManager = ClientManager.getInstance(listener, 9898);
clientManager.start();
And this is class manage the client:
public class ClientManager {
private static ServerThread serverThread = null;
private static ClientManager instance = null;
private final int port;
private ReceiveListener receiveListener = null;
private ClientManager(ReceiveListener receiveListener, int port) {
this.receiveListener = receiveListener;
this.port = port;
serverThread = new ServerThread(receiveListener, port);
}
public static ClientManager getInstance(ReceiveListener receiveListener, int port) {
if (instance == null) {
synchronized (ClientManager.class) {
if (instance == null) {
instance = new ClientManager(receiveListener, port);
}
}
}
return instance;
}
public void stop() {
serverThread.Stop();
serverThread = null;
}
public void start() {
if (serverThread == null) {
serverThread = new ServerThread(receiveListener, port);
}
new Thread(serverThread).start();
}
public static class ServerThread implements Runnable {
private ReceiveListener receiveListener;
private static Map<Integer, HandleMsgTask> tasks = new HashMap<>();
private final AtomicBoolean isExit = new AtomicBoolean(false);
private ServerSocket server;
int i = 0;
public ServerThread(ReceiveListener receiveListener, int port) {
try {
this.receiveListener = receiveListener;
this.server = new ServerSocket(port);
} catch (IOException e) {
System.out.println("failed:" + e.getMessage());
}
}
#Override
public void run() {
try {
while (!isExit.get()) {
System.out.println("wait devices... ... " + i);
Socket client = server.accept();
HandleMsgTask task = new HandleMsgTask(i, client, receiveListener);
new Thread(task).start();
tasks.put(i, task);
i++;
System.out.println("No:" + i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static class HandleMsgTask implements Runnable {
public final int clientId;
public final Socket client;
public static boolean connectStop = false;
private final ReceiveListener ReceiveListener;
public HandleMsgTask(int i, Socket client, ReceiveListener ReceiveListener) {
this.clientId = i;
this.client = client;
this.ReceiveListener = ReceiveListener;
}
public void disconnectClient() {
connectStop = true;
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
final String address = client.getRemoteSocketAddress().toString();
System.out.println(clientId + ":" + address);
InputStream inputStream = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
while (reader.ready() && !connectStop) {
String line = reader.readLine();
if (ReceiveListener != null) {
ReceiveListener.onReceived(clientId, line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void Stop() {
if (tasks != null) {
for (HandleMsgTask task : tasks.values()) {
task.disconnectClient();
}
tasks.clear();
}
isExit.set(true);
if (server != null) {
try {
server.close();
System.out.println("close server");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Could someone help me? Thanks!
As user207421 said,I misused ready(); I Change the code bellow and solve the problem:
edit:
while (!bIsStopped.get() && ((line = reader.readLine()) != null)) {
if (newMsgRecListener != null) {
newMsgRecListener.onMsgRec(clientId, line);
}
}
Related
I am currently programming an online chess game and wanted to host multiple server on 1 PC. It also works when I play with two players, but if I start a third player, it can't connect to server.
The code for the player:
public Socket socket;
public int PlayerID;
public ReadFromServer rfs;
public WriteToServer wts;
public void connectToServer(){
for (int i = 1;i <=3 ;i++ ) {
try {
socket = new Socket("localhost",(1000+i));
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
PlayerID = in.readInt();
System.out.println("You are Player Number:"+PlayerID);
if(PlayerID == 1){
System.out.println("Waiting for Oponent...");
}
rfs = new ReadFromServer(in);
wts = new WriteToServer(out);
Thread rT = new Thread(rfs);
Thread wT = new Thread(wts);
rT.start();
wT.start();
i = 4;
} catch(IOException e) {
System.out.println("ERROR at: connect to Server");
}
}
}
public static void main(String[] args) {
PlayerFrame pf = new PlayerFrame();
pf.connectToServer();
pf.GUI();
}
The Server code:
import java.io.*;
import java.net.*;
import java.net.InetAddress;
public class GameServer {
public int GameNumber = 3;
public ServerSocket ss;
public int numPlayers;
public int maxPlayers;
public Socket socket1;
public Socket socket2;
public ReadFromClient p1read;
public ReadFromClient p2read;
public WriteToClient p1write;
public WriteToClient p2write;
public GameServer[] gs;
public int p1x1,p1x2,p1y1,p1y2,p2x1,p2x2,p2y1,p2y2;
public GameServer(){
gs = new GameServer[GameNumber];
Thread[] server = new Thread[GameNumber];
ServerThread[] thread = new ServerThread[GameNumber];
for (int i = 0;i < gs.length ;i++ ) {
gs[i] = new GameServer((1000+i+1));
thread[i] = new ServerThread(i);
server[i] = new Thread(thread[i]);
server[i].start();
} // end of for
}
public GameServer(int i){
System.out.println("=====Game Server=====");
numPlayers = 0;
maxPlayers = 2;
try {
ss = new ServerSocket(i);
} catch(IOException e) {
System.out.println("ERROR at: Server Construction");
}
}
public void acceptConnections(){
try {
System.out.println("Waiting for connections...");
while (numPlayers < maxPlayers) {
Socket s = ss.accept();
DataInputStream in = new DataInputStream(s.getInputStream());
DataOutputStream out = new DataOutputStream(s.getOutputStream());
numPlayers++;
out.writeInt(numPlayers);
System.out.println("Player Number "+numPlayers+" has connected");
ReadFromClient rfc = new ReadFromClient(numPlayers,in);
WriteToClient wtc = new WriteToClient(numPlayers,out);
if(numPlayers == 1){
socket1 = s;
p1read = rfc;
p1write = wtc;
Thread read1 = new Thread(p1read);
Thread write1 = new Thread(p1write);
read1.start();
write1.start();
}
else{
socket2 = s;
p2read = rfc;
p2write = wtc;
Thread read2 = new Thread(p2read);
Thread write2 = new Thread(p2write);
read2.start();
write2.start();
}
} // end of while
System.out.println("No longer accepting connections");
} catch(IOException e) {
System.out.println("ERROR at: acceptConnections");
}
}
public static void main(String[] args) {
new GameServer();
}
public class ReadFromClient implements Runnable{
public int playerID;
public DataInputStream dataIn;
public ReadFromClient(int pid, DataInputStream in){
playerID = pid;
dataIn = in;
System.out.println("RFC "+playerID+" Runnable created");
}
#Override
public void run(){
try {
while (true) {
if(playerID == 1){
p1x1 = dataIn.readInt();
p1y1 = dataIn.readInt();
p1x2 = dataIn.readInt();
p1y2 = dataIn.readInt();
}
else{
p2x1 = dataIn.readInt();
p2y1 = dataIn.readInt();
p2x2 = dataIn.readInt();
p2y2 = dataIn.readInt();
}
try {
Thread.sleep(25);
} catch(InterruptedException ex) {
System.out.println("ERROR at RFS Run");
}
} // end of while
} catch(IOException e) {
System.out.println("ERROR at: RFS");
}
}
}
public class WriteToClient implements Runnable{
public int playerID;
public DataOutputStream dataout;
public WriteToClient(int pid, DataOutputStream out){
playerID = pid;
dataout = out;
System.out.println("WTC "+playerID+" Runnable created");
}
#Override
public void run(){
try {
while (true) {
if(playerID == 1){
dataout.writeInt(p2x1);
dataout.writeInt(p2y1);
dataout.writeInt(p2x2);
dataout.writeInt(p2y2);
dataout.flush();
}
else{
dataout.writeInt(p1x1);
dataout.writeInt(p1y1);
dataout.writeInt(p1x2);
dataout.writeInt(p1y2);
dataout.flush();
}
try {
Thread.sleep(25);
} catch(InterruptedException ex) {
System.out.println("ERROR at WTC Run");
}
} // end of while
} catch(IOException e) {
System.out.println("ERROR at: WTC run");
}
}
}
public class ServerThread implements Runnable{
public int num;
public ServerThread(int i){
num = i;
}
#Override
public void run(){
gs[num].acceptConnections();
}
}
} // end of class GameServer
I don't get any errors, even though a window doesn't pop up when I run the third player, making.
Have just one ServerSocket and a single loop, and on accepting a client socket start a game running thread using that socket.
ServerSocket serverSocket = ...
ExecutorService executorService = Executors.newFixedThreadPool(4);
while (!executorService .isTerminated()) {
Socket socket = serverSocket.accept();
Runnable gameRun = () -> { ... socket ... };
// like new WorkerThread("...");
executorService .execute(gameRun);
}
executorService .shutdown();
You can do it more neat than here, the thread and passing the socket and such.
The above runs every game conversation in its own thread.
It has one main loop on the server socket, which is crucial; you should not use the same ServerSocket in two threads.
You can easily being overrung by a DoS attack (Denial of Service, by hundreds of requests). Just keep an eye on the count of the number of threads.
On request
I cannot code here an entire client-server dialog. For that you
should look at examples, that probably are way better than what
I can write here. Also my code is not compiled.
Some code snippets.
First I would not exchange binary data, but text. That makes developing and especially debugging easier. Also with chess notation everything is almost done.
Runnable gameRun = new GameRun(socket);
executorService .execute(gameRun);
class GameRun implements Runnable, Autoclosable {
final BufferedReader in;
final PrintWriter out
GameRun(Socket socket) {
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream(),
StandardCharsets.UTF_8));
out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream(),
StandardCharsets.UTF_8)));
}
#Override
public void close() {
in.close();
out.close();
}
#Override
public void run() {
for (;;) {
out.println("Your move/action:");
if (!in.ready()) {
out.println("I am awaiting...");
//continue;
}
String line = in.readLine();
out.println("echo " + line);
if (line == null) {
break;
}
}
}
}
The client should do something similar.
I'm making code for a Server that has multiple clients that joins in it. Here's what the server's looks like.
public class Server {
private final ServerSocket serverSocket;
private static final int PORT = 9000;
private WaitingRoom wroom = new WaitingRoom();
public Server(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
public void startServer() throws InterruptedException,Exception{
try {
int count = 0;
while (!serverSocket.isClosed()) {
Socket socket = serverSocket.accept();
System.out.println("A new client has connected!");
ClientHandler clientHandler = new ClientHandler(new Player(count),socket);
Thread thread = new Thread(clientHandler);
thread.start();
count++;
System.out.println(clientHandler.getPlayer().getNickname());
wroom.join(clientHandler.getPlayer());
}
} catch (IOException e) {
closeServerSocket();
}
}
public void closeServerSocket() {
try {
if(serverSocket != null)
serverSocket.close();
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException,InterruptedException,Exception{
ServerSocket serverSocket = new ServerSocket(PORT);
Server server = new Server(serverSocket);
server.startServer();
}
}
I've a class named ClientHandler that manages these clients in a thread for each, and i pass it also in the Player class because i will use it for things like: Send msg, Receive msg. That's the ClientHandler class:
public class ClientHandler implements Runnable {
public static ArrayList<ClientHandler> clientHandlers = new ArrayList<>();
private Player player;
private String nickname;
private Socket socket;
private BufferedReader bufferedReader;
private BufferedWriter bufferedWriter;
public ClientHandler(Player player,Socket socket) throws InterruptedException,Exception{
try {
this.socket = socket;
this.bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.bufferedWriter= new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
nickname = this.bufferedReader.readLine();
player.init(nickname, this);
clientHandlers.add(this);
broadcastMessage("SERVER: " + nickname + " è entrato");
} catch (IOException e) {
closeEverything(socket, bufferedReader, bufferedWriter);
}
}
public Player getPlayer(){
return player;
}
public BufferedWriter getBufferedWriter(){
return bufferedWriter;
}
public BufferedReader getBufferedReader(){
return bufferedReader;
}
#Override
public void run() {
String messageFromClient;
while (socket.isConnected()) {
/* try {
// messageFromClient = bufferedReader.readLine();
} catch (IOException e) {
closeEverything(socket, bufferedReader, bufferedWriter);
break;
} */
}
}
public void broadcastMessage(String messageToSend) {
for (ClientHandler clientHandler : clientHandlers) {
try {
if (!clientHandler.nickname.equals(nickname)) {
clientHandler.bufferedWriter.write(messageToSend);
clientHandler.bufferedWriter.newLine();
clientHandler.bufferedWriter.flush();
}
} catch (IOException e) {
closeEverything(socket, bufferedReader, bufferedWriter);
}
}
}
private void writeToClient(String text) throws IOException{
bufferedWriter.write(text);
bufferedWriter.newLine();
bufferedWriter.flush();
}
public void removeClientHandler() {
clientHandlers.remove(this);
broadcastMessage("SERVER: " + nickname + " è uscito");
}
public void closeEverything(Socket socket, BufferedReader bufferedReader, BufferedWriter bufferedWriter) {
removeClientHandler();
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (bufferedWriter != null) {
bufferedWriter.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Now, the problem is: if I want to create a class named "WaitingRoom" for let players to waint until the wait's done. Where and how could I instantiate it? Before the linked code, i was instantiating it in the ClientHandler, but it worked only for a client a time. Here's what i wrote for the WaitingRoom class:
public class WaitingRoom {
private final int MAXPLAYERS = 2;
private ArrayList<Player> players = new ArrayList<Player>();
public ArrayList<Player> getPlayers(){
return players;
}
public void join(Player player) throws IOException,InterruptedException,Exception{
while(!addPlayer(player)){
player.sendMsg("waiting for join");
TimeUnit.SECONDS.sleep(1);
}
waitStart(player);
}
public boolean addPlayer(Player player){
if (players.size() >= MAXPLAYERS) return false;
players.add(player);
return true;
}
public boolean removePlayer(int idPlayer){
for(Player player : players){
if(player.getId() == idPlayer){
players.remove(player);
return true;
}
}
return false;
}
public void waitStart(Player player) throws IOException,InterruptedException,Exception{
if(players.size() < MAXPLAYERS)
player.sendMsg("sei entrato nella stanza d'attesa");
while(players.size() < MAXPLAYERS){
player.sendMsg("(" + players.size() + "/2) in attesa di giocatori...");
TimeUnit.SECONDS.sleep(1);
}
player.sendMsg("Inizio Gioco");
Player[] players2 = new Player[MAXPLAYERS];
for(int i=0;i<MAXPLAYERS;i++){
players2[0] = new Player(players.get(i).getId()).init(players.get(i).getNickname(),players.get(i).getClientHandler());
}
new Gioco(players2);
cleanRoom();
}
public void cleanRoom(){
players.clear();
}}
it's a really basic concept for waiting room and I only need a place where user must to wait before a gameloop. For example i don't really need multiple wainting rooms, one is ok for me, maybe.
I made a previous post a bit back working on getting a two-way server/client socket connection working. I've largely succeeded yet, but I still have one more step as a barrier. I'd like to make it so the client disconnects after they perform an operation, but the server remains up and can take in another client operation until the client makes a specific response. I'm attempting to do this through while loops in both the client and server. This is my server class:
import java.net.*;
import java.io.*;
public class ServerDemo {
private Socket mySocket = null;
private ServerSocket server = null;
private static ObjectInputStream in=null;
private static ObjectOutputStream out=null;
private static Payload myPayload=new Payload();
public ServerDemo(int port) throws ClassNotFoundException
{
double time=0;
int bytes=0;
try
{
server = new ServerSocket(port);
System.out.println("Server started");
System.out.println("Waiting for a client ...");
}
catch(IOException i)
{
System.out.println(i);
myPayload.setRepeat(false);
}
try {
while(myPayload.getRepeat()==true) {
mySocket = server.accept();
System.out.println("Client accepted");
in = new ObjectInputStream(
new BufferedInputStream(mySocket.getInputStream()));
out = new ObjectOutputStream(mySocket.getOutputStream());
myPayload.setDataPasses(10);
while (myPayload.getCurr()<myPayload.getDataPasses())
{
try
{
myPayload= (Payload) in.readObject();
myPayload.raisePasses();
out.writeObject(myPayload);
}
catch(IOException i)
{
System.out.println(i);
myPayload.setRepeat(false);
}
}
System.out.println("Closing connection");
mySocket.close();
in.close();
System.out.println("Operation Complete");
System.out.println("Client Address: "+myPayload.getClient());
System.out.println("Server Address: "+myPayload.getServer());
time=System.nanoTime()-(myPayload.getTime());
time=time/1000000000;
System.out.println("Total Time (in seconds): "+time);
bytes=(int) ( ((myPayload.getPacket().length)*myPayload.getDataPasses())/time);
System.out.println("Bytes per Second: "+bytes);
}
}
catch(IOException i)
{
System.out.println(i);
myPayload.setRepeat(false);
}
}
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
ServerDemo server=new ServerDemo(5000);
}
}
This is my client class:
import java.net.*;
import java.util.Scanner;
import java.io.*;
public class ClientDemo {
private Socket mySocket = null;
private ObjectInputStream in= null;
private ObjectOutputStream out = null;
private static long roundTrips=1;
private static Payload myPayload=new Payload();
public ClientDemo(String address, int port) throws ClassNotFoundException
{
int packageSize=1;
double time=0;
int bytes=0;
try
{
mySocket = new Socket(address, port);
System.out.println("Connected");
out = new ObjectOutputStream(mySocket.getOutputStream());
in = new ObjectInputStream(new BufferedInputStream(mySocket.getInputStream()));
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
while (myPayload.getCurr()<myPayload.getDataPasses())
{
try
{
if(myPayload.getCurr()==0) {
myPayload.setTime(System.nanoTime());
}
out.writeObject(myPayload);
myPayload= (Payload) in.readObject();
}
catch(IOException i)
{
System.out.println(i);
}
}
try
{
in.close();
out.close();
mySocket.close();
System.out.println("Operation Complete");
System.out.println("Client Address: "+myPayload.getClient());
System.out.println("Server Address: "+myPayload.getServer());
time=System.nanoTime()-(myPayload.getTime());
time=time/1000000000;
System.out.println("Total Time (in seconds): "+time);
bytes=(int) ( ((myPayload.getPacket().length)*myPayload.getDataPasses())/time);
System.out.println("Bytes per Second: "+bytes);
System.out.println("");
}
catch(IOException i)
{
System.out.println(i);
}
}
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
boolean isValid=false;
String response="";
int size=16384;
Scanner myScanner = new Scanner(System.in);
ClientDemo client=null;
String server="";
while (size>-1) {
System.out.println("Please enter a max data packet size. Enter -1 to end the program");
while(isValid==false) {
response=myScanner.next();
if(Long.parseLong(response)>=-1 && Long.parseLong(response)<=16384) {
isValid=true;
size=Integer.parseInt(response);
if(size>-1) {
myPayload.setPacket(fillPacket(size));
}
}
else {
System.out.println("Invalid Response. Please enter a value between 1 and 16384.");
}
}
if(size==-1) {
System.out.println("Closing server...");
myPayload.setRepeat(false);
client= new ClientDemo(server, 5000);
}
else {
isValid=false;
System.out.println("Please enter an amount of data passes.");
while(isValid==false) {
response=myScanner.next();
if(Long.parseLong(response)>=1) {
isValid=true;
roundTrips=Long.parseLong(response);
myPayload.setDataPasses(roundTrips);
}
else {
System.out.println("Invalid Response. Please enter a value of 1 or greater.");
}
}
isValid=false;
System.out.println("Please enter your client address.");
response=myScanner.next();
myPayload.setClient(response);
System.out.println("Please enter a server to connect to.");
response=myScanner.next();
server=response;
myPayload.setServer(server);
myPayload.reset();
client= new ClientDemo(server, 5000);
}
}
}
public static int[] fillPacket(int size) {
int[] thePacket= new int[size];
int current=0;
while(current<size) {
for(int counter=0;counter<100;counter++) {
if(current<size) {
thePacket[current]=counter;
current++;
}
}
}
return thePacket;
}
}
When I attempt to run both, the operation I have set up works completely fine, and entering -1 to close the program works but I run into errors when performing operations beyond that. Attempting to set size to -1 to end the program at this point causes an endless loop of
java.io.EOFException
inside ServerDemo, while entering what should be a valid packet size between 0 and 16384 instead produces an endless stream of
java.net.SocketException: Broken pipe (Write failed)
inside ClientDemo. Perhaps most strangely, the latter error only SOMETIMES occurs, not always. If anyone has any pointers on how to get this correctly working and remedying these errors, I would greatly appreciate it!
I would rather change approach. The usual one when doing this kind of stuff is create a thread to listen on your port, then, when a client connects, immediately dispatch the new task to a thread pool and continue listening.
This way not only your server will continue listening after the client disconnects, but also will be able to serve multiple clients in parallel (up to the thread pool size).
Also please use try-with-resources whenever possible to easily avoid resource leaking.
So your code could be changed to something like this:
Server class
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerDemo {
private int port;
private Thread listenThread;
private ExecutorService serverPool;
public ServerDemo(int port) {
this.port = port;
}
public synchronized void startServer() {
serverPool = Executors.newFixedThreadPool(4);
listenThread = new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println(String.format("Listening on port %d", port));
System.out.println("1");
while (!Thread.interrupted()) {
System.out.println("2");
Socket clientSocket = serverSocket.accept();
System.out.println("3");
if(!Thread.currentThread().isInterrupted())
serverPool.submit(new ClientTask(clientSocket));
System.out.println("4");
}
} catch (IOException e) {
System.err.println("Error processing client connection");
e.printStackTrace();
}
System.out.println("ListenThread stopped");
}, "ListenThread");
listenThread.start();
}
public synchronized void stopServer() {
System.out.println("Stopping server...");
if (serverPool != null) {
serverPool.shutdown();
serverPool = null;
}
if(listenThread != null) {
listenThread.interrupt();
try (Socket voidSocket = new Socket("localhost", port)) {
// Void socket to unlock the accept() call
} catch (IOException e) {
}
listenThread = null;
}
}
private class ClientTask implements Runnable {
private final Socket clientSocket;
private ClientTask(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Client accepted");
Payload myPayload = new Payload();
try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(clientSocket.getInputStream()));
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream())) {
myPayload.setDataPasses(10);
while (myPayload.getCurr() < myPayload.getDataPasses()) {
try {
myPayload = (Payload) in.readObject();
myPayload.raisePasses();
out.writeObject(myPayload);
} catch (IOException i) {
System.out.println(i);
break;
} catch (ClassNotFoundException e) {
System.err.println("Error finding class to deserialize");
e.printStackTrace();
}
}
System.out.println("Operation Complete");
System.out.println("Client Address: " + myPayload.getClient());
System.out.println("Server Address: " + myPayload.getServer());
double time = System.nanoTime() - (myPayload.getTime());
time = time / 1000000000;
System.out.println("Total Time (in seconds): " + time);
int bytes = (int) (((myPayload.getPacket().length) * myPayload.getDataPasses()) / time);
System.out.println("Bytes per Second: " + bytes);
} catch (IOException e1) {
System.err.println("Error opening client I/O streams");
e1.printStackTrace();
}
try {
System.out.println("Closing connection");
clientSocket.close();
} catch (IOException e) {
System.err.println("Error closing client connection");
e.printStackTrace();
}
if(!myPayload.getRepeat())
stopServer();
}
}
public static void main(String[] args) throws ClassNotFoundException {
ServerDemo server = new ServerDemo(5000);
server.startServer();
// do other stuff including trapping for sigterm, then call server.stopServer() if needed
}
}
Client class
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class ClientDemo {
private static void executeClientJob(Payload myPayload, int port) {
double time = 0;
int bytes = 0;
try (Socket mySocket = new Socket(myPayload.getServer(), port);
ObjectOutputStream out = new ObjectOutputStream(mySocket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(mySocket.getInputStream()))) {
System.out.println("Connected");
while (myPayload.getCurr() < myPayload.getDataPasses()) {
if (myPayload.getCurr() == 0)
myPayload.setTime(System.nanoTime());
out.writeObject(myPayload);
myPayload = (Payload) in.readObject();
}
System.out.println("Operation Complete");
System.out.println("Client Address: " + myPayload.getClient());
System.out.println("Server Address: " + myPayload.getServer());
time = System.nanoTime() - (myPayload.getTime());
time = time / 1000000000;
System.out.println("Total Time (in seconds): " + time);
bytes = (int) (((myPayload.getPacket().length) * myPayload.getDataPasses()) / time);
System.out.println("Bytes per Second: " + bytes);
System.out.println("");
} catch (UnknownHostException u) {
u.printStackTrace();
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
c.printStackTrace();
}
}
private static void testAutomatic() {
for (int i = 0; i < 1; i++) {
Payload myPayload = new Payload();
myPayload.setPacket(fillPacket(40));
executeClientJob(myPayload, 5000);
}
Payload stopPayload = new Payload();
stopPayload.setRepeat(false);
executeClientJob(stopPayload, 5000);
}
private static void testInteractive() {
Payload myPayload;
boolean repeat;
do {
myPayload = readPayloadSettings();
repeat = myPayload.getRepeat();
executeClientJob(myPayload, 5000);
} while (repeat);
}
private static Payload readPayloadSettings() {
Payload ret = new Payload();
int size = 60;
#SuppressWarnings("resource")
Scanner myScanner = new Scanner(System.in);
System.out.println("Please enter a max data packet size. Enter -1 to end the program");
while (true) {
String response = myScanner.next();
if (Long.parseLong(response) >= -1 && Long.parseLong(response) <= 16384) {
size = Integer.parseInt(response);
break;
} else {
System.out.println("Invalid Response. Please enter a value between 1 and 16384.");
}
}
if (size == -1) {
System.out.println("Closing server...");
ret.setRepeat(false);
} else {
ret.setPacket(fillPacket(size));
System.out.println("Please enter an amount of data passes.");
while (true) {
String response = myScanner.next();
if (Long.parseLong(response) >= 1) {
ret.setDataPasses(Long.parseLong(response));
break;
} else {
System.out.println("Invalid Response. Please enter a value of 1 or greater.");
}
}
System.out.println("Please enter your client address.");
ret.setClient(myScanner.next());
System.out.println("Please enter a server to connect to.");
ret.setServer(myScanner.next());
}
return ret;
}
public static int[] fillPacket(int size) {
int[] thePacket = new int[size];
int current = 0;
while (current < size) {
for (int counter = 0; counter < 100; counter++) {
if (current < size) {
thePacket[current] = counter;
current++;
}
}
}
return thePacket;
}
public static void main(String[] args) throws ClassNotFoundException {
testInteractive();
//testAutomatic();
}
}
Payload class (with defaults to quick create an automatic test)
import java.io.Serializable;
public class Payload implements Serializable {
private int curr=0;
private long dataPasses=5;
private long time;
private String client="localhost";
private String server="localhost";
private int[] packet=new int[0];
private boolean repeat=true;
public Payload() {
}
public int getCurr() {
return curr;
}
public void setCurr(int curr) {
this.curr = curr;
}
public long getDataPasses() {
return dataPasses;
}
public void setDataPasses(long roundTrips) {
this.dataPasses = roundTrips;
}
public long getTime() {
return time;
}
public void setTime(long nanoTime) {
time = nanoTime;
}
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public int[] getPacket() {
return packet;
}
public void setPacket(int[] packet) {
this.packet = packet;
}
public boolean getRepeat() {
return repeat;
}
public void setRepeat(boolean r) {
this.repeat = r;
}
public void reset() {
curr=0;
dataPasses=0;
}
public void raisePasses() {
curr++;
}
}
I have a simple rmi-server and rmi-client. When i run this server and client in same network, my server function returns the result properly. But my server and client are in different networks and if the process time is more than 3-4 minutes client can not get the result, although server fihishes the operation.
here is my entire server code:
public class SimpleServer {
ServerRemoteObject mRemoteObject;
public static int RMIInPort = 27550;
public static int delay = 0;
public byte[] handleEvent(byte[] mMessage) throws Exception {
String request = new String(mMessage, "UTF-8");
// if ("hearthbeat".equalsIgnoreCase(request)) {
// System.out.println("returning for hearthbeat");
// return "hearthbeat response".getBytes("UTF-8");
// }
System.out.println(request);
Thread.sleep(delay);
System.out.println("returning response");
return "this is response".getBytes("UTF-8");
}
public void bindYourself(int rmiport) {
try {
mRemoteObject = new ServerRemoteObject(this);
java.rmi.registry.Registry iRegistry = LocateRegistry.getRegistry(rmiport);
iRegistry.rebind("Server", mRemoteObject);
} catch (Exception e) {
e.printStackTrace();
mRemoteObject = null;
}
}
public static void main(String[] server) {
int rmiport = Integer.parseInt(server[0]);
RMIInPort = Integer.parseInt(server[1]);
delay = Integer.parseInt(server[2]);
System.out.println("server java:" + System.getProperty("java.version"));
System.out.println("server started on:" + rmiport + "/" + RMIInPort);
System.out.println("server delay on:" + delay);
SimpleServer iServer = new SimpleServer();
iServer.bindYourself(rmiport);
while (true) {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and here is my client code:
public class SimpleClient {
ISimpleServer iServer;
public SimpleClient(String p_strServerIp, String p_strCMName, int nRMIPort) {
try {
if (nRMIPort == 1099) {
iServer = (ISimpleServer) Naming.lookup("rmi://" + p_strServerIp + "/" + p_strCMName);
} else {
Registry rmiRegistry = null;
rmiRegistry = LocateRegistry.getRegistry(p_strServerIp, nRMIPort);
iServer = (ISimpleServer) rmiRegistry.lookup(p_strCMName);
}
} catch (Exception ex) {
ex.printStackTrace();
iServer = null;
}
}
public static void main(String... strings) {
String ip = strings[0];
int rmiport = Integer.parseInt(strings[1]);
System.out.println("client java:" + System.getProperty("java.version"));
System.out.println("client is looking for:" + ip + ":" + rmiport);
SimpleClient iClient = new SimpleClient(ip, "Server", rmiport);
try {
byte[] response = iClient.iServer.doaction("this is request".getBytes("UTF-8"));
System.out.println(new String(response, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
and here is my rmi-registry code:
public class SimpleRMI implements Runnable {
Registry mRegistry = null;
public SimpleRMI(int nPort) {
try {
mRegistry = new sun.rmi.registry.RegistryImpl(nPort);
} catch (RemoteException e1) {
e1.printStackTrace();
}
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(360000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String... strings) {
int rmiport = Integer.parseInt(strings[0]);
System.out.println("rmi java:" + System.getProperty("java.version"));
System.out.println("rmi started on:" + rmiport);
SimpleRMI iRegisry = new SimpleRMI(rmiport);
Thread tThread = new Thread(iRegisry);
tThread.start();
byte[] bytes = new byte[1];
while (true) {
try {
System.in.read(bytes);
if (bytes[0] == 13) {
try {
iRegisry.listRegistry();
} catch (Exception exc2) {
exc2.printStackTrace();
}
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
private void listRegistry() {
String[] strList = null;
try {
strList = mRegistry.list();
if (strList != null) {
for (int i = 0; i < strList.length; i++) {
int j = i + 1;
String name = strList[i];
java.rmi.Remote r = mRegistry.lookup(name);
System.out.println(j + ". " + strList[i] + " -> "
+ r.toString());
}
}
System.out.println();
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
and my remote interface and remote object:
public interface ISimpleServer extends java.rmi.Remote {
public byte[] doaction(byte[] message) throws java.rmi.RemoteException;
}
#SuppressWarnings("serial")
public class ServerRemoteObject extends UnicastRemoteObject implements ISimpleServer {
SimpleServer Server = null;
public ServerRemoteObject(SimpleServer pServer) throws RemoteException {
super(SimpleServer.RMIInPort);
Server = pServer;
}
#Override
public byte[] doaction(byte[] message) throws RemoteException {
try {
return Server.handleEvent(message);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
when i run client and server in different networks. (i run client in my home network) and if delay is more than 3-4 mins server prints returning response but client still waits for the response. If delay is only 1 minute, clients gets the result properly.
Can you please help me to find where the problem is?
I am working on a project trying to make several people be able to control a robot arm. For this they have to connect to a Java server that then sends the commands to a robot screen for video conferencing.
I am trying to have a thread for each client and then I want to be able to switch between the different clients based on sound, because I want the speaker to be able to control the robot.
The clients all provide positional data and the level of sound taken by the kinect, and sent to the server in the form of a string.
I am having problems with performing the switch. Currently they seem to be switching back and forth and it makes the robot go haywire.
Is there a good way of comparing the threads to each other, find the appropriate one, switch to that, all the while checking the other threads to see if or when they become the most appropriate one? While also checking in case other clients try to connect to the server?
Thank you for your help.
I also include my code in case you want to look through it and get a better idea.
This is the server class:
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Hashtable;
public class MultiThreadedServer implements Runnable {
protected int serverPort = 8888;
protected ServerSocket serverSocket = null;
protected boolean isStopped = false;
protected Thread runningThread = null;
protected Thread clientThread = null;
protected Thread threadThread = null;
private Hashtable<Long, WorkerRunnable> Users = new Hashtable<Long, WorkerRunnable>();
private ArrayList<Thread> ClientThreads = new ArrayList<Thread>();
private WorkerRunnable client = null;
private ThreadHandler threadHandler = null;
private int sound_max = 0;
private boolean once = true;
public MultiThreadedServer (int port) {
this.serverPort = port;
}
public void run() {
synchronized(this) {
this.runningThread = Thread.currentThread();
}
openServerSocket();
threadHandler = new ThreadHandler();
while( !isStopped() ) {
Socket clientSocket = null;
try {
System.out.println(InetAddress.getLocalHost());
clientSocket = this.serverSocket.accept(); // Connect to clients
} catch (SocketTimeoutException e) {
} catch (IOException e) {
if( isStopped() ) {
System.out.println("Server Stopped");
return;
}
throw new RuntimeException("Error accepting client connection", e);
}
client = new WorkerRunnable(clientSocket, "Multithreaded Server");//Class does client work
clientThread = new Thread(client); // Make a thread for each client
clientThread.start(); // start thread
threadHandler.setUp(client, clientThread); // Set up the thread handler
if ( once == true) { // make sure the threadHandler thread is only created once
threadThread = new Thread(threadHandler);
threadThread.start();
once = false;
}
}
System.out.println("Server Stopped");
}
/**
* Check if the socket is stopped
* #return true if the socket is stopped
*/
private synchronized boolean isStopped() {
return this.isStopped;
}
/**
* Stop and close the socket
*/
public synchronized void stop() {
this.isStopped = true;
try {
this.serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
/**
* Open server socket
*/
private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port 8888", e);
}
}
}
This is the Worker class, that handles the data from the clients:
import gnu.io.NoSuchPortException;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class WorkerRunnable implements Runnable {
protected Socket clientSocket = null;
protected String serverText = null;
private BufferedReader inFromClient;
private DataOutputStream outToClient;
private int[] currentPos = new int[6];
private boolean connected = false;
static TwoWaySerialComm serialCom = null;
static MultiServoState mState;
static int sound_average;
int[] degrees = new int[7];
int count = 0;
public WorkerRunnable(Socket clientSocket, String serverText) {
this.clientSocket = clientSocket;
this.serverText = serverText;
initCurrentPos();
if (serialCom == null) {
serialCom = new TwoWaySerialComm();
}
try {
if (!serialCom.isConnected("COM5")) {
try {
serialCom.connect("COM5");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mState = new MultiServoState(serialCom);
}
} catch (NoSuchPortException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
try {
work();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
}
}
public void work() throws InterruptedException {
try {
InputStream input = clientSocket.getInputStream();
OutputStream output = clientSocket.getOutputStream();
inFromClient = new BufferedReader(new InputStreamReader(input));
outToClient = new DataOutputStream(output);
long time = System.currentTimeMillis();
updateData();
String message = null;
long endTime = System.currentTimeMillis() + 2000;
while ((message = (String) inFromClient.readLine()) != null) {
System.out.println("Message Received: " + message);
parse(message);
sound_average = degrees[6];
//
// Send the positional data to the robot
//
mState.runServo(degrees[0], degrees[1], degrees[2],
degrees[3], degrees[4], degrees[5]);
//
// Send a response information to the client application
//
currentPos[0] = mState.getCurrentPos(0);
currentPos[1] = mState.getCurrentPos(1);
currentPos[2] = mState.getCurrentPos(2);
currentPos[3] = mState.getCurrentPos(3);
currentPos[4] = mState.getCurrentPos(4);
try {
updateData();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Request processed: " + time);
} catch (IOException e) {
// report exception somewhere
e.printStackTrace();
}
}
/**
* Initiate the robot's starting position.
*/
public void initCurrentPos()
{
currentPos[0] = 100;
currentPos[1] = 100;
currentPos[2] = 100;
currentPos[3] = 100;
currentPos[4] = 100;
currentPos[5] = 0;
}
/**
* Send the data to the client
*
* #throws IOException
*/
public void updateData() throws IOException {
String sentence = Integer.toString(currentPos[0]) + ", " +
Integer.toString(currentPos[1]) + ", " +
Integer.toString(currentPos[2]) + ", " +
Integer.toString(currentPos[3]) + ", " +
Integer.toString(currentPos[4]) + "." + "\n";
outToClient.flush();
outToClient.writeBytes(sentence);
}
/**
* Get the clients sound average
* #param message
*/
public int getSoundAverage() {
return sound_average;
}
public void parse(String message) {
if (message != null) {
char c;
StringBuilder sb = new StringBuilder(4);
int j = 0;
boolean help = false;
for (int i = 0; i < message.length(); i++) {
c = message.charAt(i);
if (Character.isDigit(c)) {
sb.append(c);
help = true;
}
if (!Character.isDigit(c) && help == true) {
degrees[j] = Integer.parseInt(sb.toString());
j++;
help = false;
sb.delete(0, sb.length());
}
}
}
System.out.println("Waiting for client message...");
}
/**
* Close all connections
*/
public void close() {
if (connected) {
synchronized (this) {
connected = false;
}
if (outToClient != null) {
try {
outToClient.close();
synchronized (this) {
outToClient = null;
}
} catch (IOException e) {
// there is nothing we can do: ignore it
}
}
if (inFromClient != null) {
try {
inFromClient.close();
synchronized (this) {
inFromClient = null;
}
} catch (IOException e) {
// there is nothing we can do: ignore it
}
}
if (clientSocket != null) {
try {
clientSocket.close();
synchronized (this) {
clientSocket = null;
}
} catch (IOException e) {
// there is nothing we can do: ignore it
}
}
}
}
public void returnThread() {
return;
}
}
The final class is the thread handler where I try to compare sound levels and yield all threads except the loudest one:
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Hashtable;
import com.research.aserver.WorkerRunnable;
public class ThreadHandler implements Runnable {
protected boolean isStopped = false;
protected Thread runningThread = null;
protected Thread clientThread = null;
private Hashtable<Long, WorkerRunnable> Users = new Hashtable<Long, WorkerRunnable>();
private ArrayList<Thread> ClientThreads = new ArrayList<Thread>();
private WorkerRunnable client = null;
private int sound_max = 0;
private int index = 0;
public ThreadHandler() {
}
public void setUp(WorkerRunnable client, Thread clientThread) {
this.client = client;
this.clientThread = clientThread;
Users.put(clientThread.getId(), this.client); // Place clients in a list with its thread ID as key
ClientThreads.add(this.clientThread); // List of client threads
}
#Override
public void run() {
long endTime = System.currentTimeMillis() + 2000; // Help variable to check every 2 sec
while (!Users.isEmpty() && !ClientThreads.isEmpty()) {
for (int i = 0; i < ClientThreads.size(); i++) { // Remove clients and threads if no longer active
if (!ClientThreads.get(i).isAlive()) {
Users.remove(ClientThreads.get(i).getId());
ClientThreads.get(i).interrupt();
ClientThreads.remove(i);
}
}
if(System.currentTimeMillis() >= endTime) { // Do work every 2 sec
for (int i = 0; i < ClientThreads.size(); i++) { // Get the client with the loudest sound
if (sound_max < Users.get(ClientThreads.get(i).getId()).getSoundAverage()) {
sound_max = Users.get(ClientThreads.get(i).getId()).getSoundAverage();
index = i;
}
}
for (int i = 0; i < ClientThreads.size(); i++) { // yield all threads that are not the loudest
if (Users.get(ClientThreads.get(index).getId()) != Users.get(ClientThreads.get(i).getId())){
ClientThreads.get(i).yield();
index = 0;
}
}
endTime = System.currentTimeMillis() + 2000; // update time
}
sound_max = 0;
}
}
}
One idea might be to use a PriorityBlockingQueue and define a quality value for each input, which is then sort by quality automatically inside the list.
Using this your consumer thread can simply fetch the first one in line and process it, knowing that it is the most appropriate one, while the generator threads can simply throw all input in the Queue.