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.
Related
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 want to send an object having OS Name to a server. This OS Name output should be of PC sending object but it displays OS Name of PC running server..
Here is my code :
//Client : it can send data i.e. object to server
class Client
{
private Socket socket = null;
private ObjectOutputStream outputStream = null;
public Client(String con){
System.out.println("conn value: "+con);
java.util.Timer t = new java.util.Timer();
try{
socket = new Socket(con, 27051);
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
outputStream = new ObjectOutputStream(socket.getOutputStream());
SI sysinfo=new SI();
outputStream.writeObject(sysinfo);
System.out.println("Sent Data: "+sysinfo.otherInfo());
} catch (Exception se) {
t.cancel();
}
}
}, 0, 1);
}
catch(Exception em)
{
}
}
}
//Server class: should receive data from client
class Server extends SwingWorker<Void,Void>{
Socket csocket=null;
protected Void doInBackground() throws Exception {
final ServerSocket ssock = new ServerSocket(27051);
System.out.println("Server Listening..!!");
while (true) {
try{
Socket sock = ssock.accept();
new Thread(new Server(sock)).start();
}
catch(Exception e){
System.out.println("unabke to create socket");
}
}
}
Server() throws Exception{
doInBackground();
}
Server(Socket csocket) {
this.csocket=csocket;
Thread t1=new Thread(r1);
t1.start();
}
Runnable r1=new Runnable()
{
public void run() {
try {
System.out.println("Run initated");
while(true)
{
if(csocket.isClosed())
{
break;
}
else{
System.out.println(csocket);
ObjectInputStream inStream = new
ObjectInputStream(csocket.getInputStream());
SI sysinfo= (SI) inStream.readObject();
System.out.println("Received: "+sysinfo.otherInfo());
System.out.println(ObjectStreamClass.lookup(sysinfo.getClass()).getSerialVersion
UID());
}
}
}
catch (Exception e) {
System.out.println("Exception"+ e.getMessage());
}
}
};
}
//class undergoing serialization
public class SI implements Serializable
{
private static final long serialVersionUID = 1L;
String otherInfo()
{
OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
.getOperatingSystemMXBean();
String os_name=bean.getName();
return os_name;
}
}
//class A: It has main function and it executes first and user decides whether he/she want to be in server mode or in client mode. As user cannot be in 2 modes simultaneously..
class A
{
public static void main(String[] args) throws Exception
{
System.out.println("Enter 0 for Server 1 for Client Mode");
Scanner s=new Scanner(System.in);
int i=s.nextInt();
if(i==0)
{
Server ser=new Server();
ser.execute();
}
else if(i==1)
{
System.out.println("Enter IP");
String conn=s.next();
Client c=new Client(conn);
}
else
System.out.println("Invalid Selection exit..");
}
}
As I wrote in my comment you must transfer the data, not the function. Some sample code below...
First, change your SI class as follows:
public class SI implements Serializable {
private static final long serialVersionUID = 1L;
private String osName;
public void setOsName(String osName) { this.osName = osName; }
public void getOsName() { return this.osName; }
}
Second, modify your client to first determine the OS and the build the SI object...
...
OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
.getOperatingSystemMXBean();
String osName=bean.getName();
SI sysinfo = new SI();
sysinfo.setOsName(osName);
...
outputStream.writeObject(sysinfo);
...
Third, modify your server accordingly.
I'm creating a token ring with sensors where every sensor is a process apart. When i start a sensor it communicates with the gateway and gets the list of the actual sensors already on the system .
The problem is that every time i start a new process i want every already existing sensor to get the updated list, so to understand that other sensors have been added and the list is no longer the one they had but a new updated one.(So lets say the processes must always have the same list). I use a server which i call serverSocket which listens for messages. I can make it possible for the server to understand that the list has been changed but what i cant do is how to change the value of the sensorList found on my SensorClient class, to be updated? In the code bellow i show what i'm doing but the sensorList keeps being the old one,not being updated :/ Can anyone please help me? Thank you :)
SensorClient where i start a new process sensor
public class SensorClient {
public static void main(String[] args) throws Exception {
Sensor sensor = new Sensor(type,identificator,portnumber,ipnumber,gatewayAddr,timestamp);
Gson gson = new Gson();
String message = gson.toJson(sensor);
Client c = Client.create();
WebResource r = c.resource("http://localhost:9999/gateway/");
ClientResponse response = r.path("sensors/add").type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, message);
if (response.getStatus() == 200) {
repeat = false;
Type collectionType = new TypeToken<ArrayList<Sensor>>(){}.getType();
ArrayList<Sensor> sensorList = gson.fromJson(response.getEntity(String.class), collectionType);
System.out.println("Starting the sensor ...");
System.out.println("Push exit when you want to delete the sensor!");
int position = 0;
for(int i = 0; i< sensorList.size();i++){ if(sensorList.get(i).getIdentificator().equalsIgnoreCase(sensor.getIdentificator()) ) position = i;
}
sensors.Sensor.simulation(type, identificator);// special thread for sensors simulations
createSensor.getInstance().setPrevNextWhenAdd(position,sensorList);
serverSocket serverSocket = new serverSocket(portnumber,sensorList,position,sensorList.get(position).getNext());
serverSocket.start();
StopSensor stopSensor = new StopSensor(identificator,portnumber,position,sensorList);
stopSensor.start();
oneSensor s = new oneSensor(portnumber,sensorList);
s.start();
} else {
repeat = true;
count +=1;
System.out.println("Error. Wrong data! ");
}
}
while (repeat );
}
}
}
The serverSocket thread
public class serverSocket extends Thread {
public int port,nextPort;
ArrayList<gateway.Sensor> sensorList;
public static int position;
public serverSocket(int port, ArrayList<gateway.Sensor> sensorList,int position,int nextPort) {
this.port = port;
this.nextPort=nextPort;
this.sensorList= sensorList;
this.position=position;}
public void run() {
ServerSocket welcomeSocket;
Socket connectionSocket;
try {
welcomeSocket = new ServerSocket(port);
while (true) {
connectionSocket = welcomeSocket.accept();
receivedMessages thread = new receivedMessages(connectionSocket,sensorList,position,nextPort);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
System.err.println("Error!!!!!!!!!");
}
}
}
The receivedMessages thread
public class receivedMessages extends Thread {
private BufferedReader inFromClient;
private Socket connectionSocket;
ArrayList<gateway.Sensor> sensorList;
int position,nextPort;
public receivedMessages(Socket socket, ArrayList<gateway.Sensor> sensorList,int position,int nextPort){
connectionSocket = socket;
this.sensorList=sensorList;
this.position=position;
this.nextPort=nextPort;
try {
inFromClient = new BufferedReader( new InputStreamReader(connectionSocket.getInputStream()));
} catch (IOException e) { e.printStackTrace(); }
}
#Override
public void run() {
try {
String message = (inFromClient.readLine().toString());
if (message.startsWith("Next") || message.startsWith("Previous")) {
System.out.println(message);
} else if (message.startsWith("The")) {
System.out.println(message); createSensor.getInstance().setPrevNextWhenDelete(position, sensorList);
} else {// i receive the message that the list has changed
System.out.println(message);
sensorList = createSensor.getInstance().getSensorList();
System.out.println("Updated " + sensorList);}
This class has methods used by gateway to register a sensor when it makes the request
public class createSensor {
private static createSensor instance = null;
private ArrayList<Sensor> sensor = new ArrayList<>();
public int position, prevPosition, nextPosition, prevPort, nextPort;
private createSensor() { }
public static synchronized createSensor getInstance() {
if (instance == null) {
instance = new createSensor();
}
return instance;
}
public synchronized ArrayList insertSensor(String type, String identificator, int port, String id, String gatwayAddr, long timestamp) throws IOException {
sensor.add(new Sensor(type, identificator, port, id, gatwayAddr, timestamp));
return new ArrayList<>(sensor); //
}
}
public synchronized boolean hasMeasurements() {
while (InnerBuffer.getInstance().emptyInnerBuffer())
return false;
return true;
}
public synchronized void setPrevNextWhenDelete(int position,ArrayList<Sensor> sensorList) throws IOException {
//code
}
public synchronized ArrayList<Sensor> getSensorList() {
return new ArrayList<>(sensor);
}
public synchronized int size() {
return sensor.size();
}
public synchronized String returnRecentMeasurement (String id){
String recentMeasurement=null;
for (Sensor sensori : sensor) {
if (sensori.getIdentificator().equalsIgnoreCase(id))
recentMeasurement= InnerBuffer.getInstance().returnRecentMeasurements(id);
else
recentMeasurement = null;}
return recentMeasurement;
}
public synchronized void setPrevNextWhenAdd() throws IOException { //some other code where int position, prevPosition, nextPosition, prevPort, nextPort get their values. }}
So, I was trying to create a chat for multiple users via client-server communication. Connecting and chatting works quite nicely already, however, if one client disconnects from the server (triggered by the keyword exit as the program is console-based atm because the UI is not yet finished), one of the other ClientIO-Threads shuts down additionally to the one related to the disconnecting client. I just don't have any idea why, as those Threads only handle the output of the client that is sending a message.
I tested the program with 3 clients. It seems that if you close client 1 or 2 (with exit; ID in order of connection, starting at 0), the ClientIO-Thread of client 0 shuts down. If you close client 0, Thread 1 shuts down.
Why does that happen? How do I fix it?
Please go easy on me if there's something wrong about how I put the question, first time I ask myself. Thanks in advance!
Code:
Server:
class Server:
import java.io.*;
import java.net.*;
public class Server extends Thread{
int n = 0;
private Socket angekommenerClient;
private ServerSocket sSocket;
Liste client_Liste;
public Server (int port) {
try {
//System.out.println("konst1");
sSocket = new ServerSocket (port);
//System.out.println("konst2");
client_Liste=new Liste();
}catch (Exception e){e.printStackTrace();}
}
public void run(){
try {
//System.out.println("try");
InputStreamReader isr;
BufferedReader br;
while (true) {
//System.out.println("while");
/**Verbindungsannahme**/
angekommenerClient = sSocket.accept();
System.out.println("accept");
InputStream input=angekommenerClient.getInputStream();
OutputStream output=angekommenerClient.getOutputStream();
/**Übergabe Username**/
isr = new InputStreamReader(input);
br = new BufferedReader(isr);
String username = br.readLine();
/**Datenerfassung**/
client_PC neu = new client_PC(angekommenerClient,output,angekommenerClient.getInetAddress(), n, username);
client_Liste.insert(neu);
n++;
client_Liste.toFirst();
System.out.println("test "+((client_PC)client_Liste.getObject()).getID());
/**Vebindungsaufbau**/
new Connection (neu, new BufferedReader(new InputStreamReader(input)));
}
}catch (Exception e){e.printStackTrace();}
}
class Connection{
private BufferedReader client_input; // vom Client
private client_PC client;
private String client_anwender;
private ClientIO cIO;
public Connection(client_PC c, BufferedReader ci){
client=c;
client_input=ci;
cIO=new ClientIO();
cIO.start();
}
class ClientIO extends Thread{
boolean closed = false;
public void run(){
PrintStream ps = null;
while(!client.getSocket().isClosed() && !closed){
try{
if(client_input.ready()){
if(!client_Liste.isEmpty()){
/**Nachricht einlesen**/
System.out.println("listen");
String msg = client_input.readLine();
System.out.println("Input: "+msg);
/**Abmeldung erfahren**/
if(msg.equals("exit")){
closed = true;
}
/**Nachricht weiterleiten...**/
client_Liste.toFirst();
while(client_Liste.hasAccess()){
client_PC cpc = ((client_PC)client_Liste.getObject());
System.out.println("ID: "+cpc.getID());
/**...außer an sich selbst**/
if(cpc.getID()!=client.getID()){
ps = new PrintStream(cpc.getOutput());
ps.println(client.getUsername() + "(" + client.getID() + "): " + msg);
}
client_Liste.next();
}
System.out.println("finish");
}
}
}catch(Exception e){e.printStackTrace();};
}
/**Offenes schließen**/
if(ps != null){
ps.close();
}
System.out.println("disconnected" + client.getID());
stop();
}
}
}
}
class client_PC:
import java.io.*;
import java.net.*;
public class client_PC{
private Socket client_Socket;
private OutputStream client_Output;
private InetAddress client_IP;
private Object client_Info=null;
private int ID;
private String username;
public client_PC(Socket c_Socket,OutputStream c_Output,InetAddress c_IP, int id, String uname){
client_Socket=c_Socket;
client_Output=c_Output;
client_IP=c_IP;
ID = id;
username = uname;
}
public InetAddress getInetAddress(){
return client_IP;
}
public Socket getSocket(){
return client_Socket;
}
public int getID(){
return ID;
}
public OutputStream getOutput(){
return client_Output;
}
public void setInfo(Object info){
client_Info=info;
}
public Object getInfo(){
return client_Info;
}
public String getUsername(){
return username;
}
}
class Liste:
public class Liste{
private ListElement ListKopf;
private ListElement VorAktuellerZeiger, AktuellerZeiger;
Liste(){
ListKopf=null;
AktuellerZeiger=null;
VorAktuellerZeiger=null;
}
boolean isEmpty(){
return (ListKopf==null);
}
public boolean hasAccess() {
return (!this.isEmpty() && AktuellerZeiger!=null);
}
public void next(){
if (this.hasAccess()){
ListElement Hilf=AktuellerZeiger;
AktuellerZeiger=AktuellerZeiger.naechstes;
VorAktuellerZeiger=Hilf;
}
}
public void toFirst() {
AktuellerZeiger=ListKopf;
VorAktuellerZeiger=null;
}
public void toLast() {
if(!hasAccess())this.toFirst();
if(AktuellerZeiger!=null){
while(AktuellerZeiger.naechstes!=null)
next();
}
}
public Object getObject(){
if (this.hasAccess())
return AktuellerZeiger.Inhalt;
else
return null;
}
public void setObject(Object pObject){
if (pObject!=null && this.hasAccess()){
remove();
insvor(pObject);
}
}
private void insvor(Object x){
ListElement Neu= new ListElement(x,AktuellerZeiger);
if(VorAktuellerZeiger==null){ListKopf=Neu; AktuellerZeiger=Neu;}
else {VorAktuellerZeiger.naechstes=Neu;}
}
private void insnach(Object x){
next();
insvor(x);
}
public void insert(Object pObject){
if (pObject!=null)
insvor(pObject);
}
public void append(Object pObject){
if (pObject!=null){
this.toLast();
if(this.hasAccess())
insnach(pObject);
}
}
public void remove(){
if(AktuellerZeiger!=null){
AktuellerZeiger=AktuellerZeiger.naechstes;
if(VorAktuellerZeiger==null){ListKopf=AktuellerZeiger;}
else {VorAktuellerZeiger.naechstes=AktuellerZeiger;}
}
}
}
class ListElement:
public class ListElement{
protected Object Inhalt;
protected ListElement naechstes;
ListElement (Object x, ListElement n){
Inhalt = x;
naechstes = n;
}
}
Client:
class Client:
import java.io.*;
import java.net.*;
public class Client
{
//String IP = "10.16.139.3";
String IP = "localhost";
String name;
int port = 5000;
Socket socket;
ClientThread t1, t2;
public Client(String n){
name = n;
}
public void main() throws IOException{
/**Socket**/
socket = new Socket(IP, port);
/**Übergabe Name**/
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(name);
/**Verbindungs-Threads**/
t1 = new ClientThread(System.in, socket.getOutputStream(), true);
t2 = new ClientThread(socket.getInputStream(), System.out, false);
t1.start();
t2.start();
while(t1.isAlive() && t2.isAlive()){}
ps.close();
socket.close();
}
}
class ClientThread:
import java.awt.*;
import java.lang.*;
import java.io.*;
import java.net.*;
public class ClientThread extends Thread{
boolean halt = false, isSender;
InputStream is;
InputStreamReader isr;
BufferedReader br;
String msg;
OutputStream os;
PrintStream ps;
public ClientThread(InputStream s1, OutputStream s2, boolean s)
{
try{
isSender = s;
is = s1;
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = s2;
ps = new PrintStream(os);
}catch(Exception e){e.printStackTrace();}
}
public void run(){
while (!halt){
try{
if(br.ready()){
msg = br.readLine();
if(msg != null){
ps.println(msg);
if((msg.equals("exit") || msg.trim().equals("null"))&&isSender){stopp(); stop();}
}
else{
System.out.println("Error msg: "+msg);
}
}
}catch(Exception e){e.printStackTrace();}
}
}
public void stopp(){
halt = true;
}
public void weiter(){
halt = false;
}
}