I'm trying to write a messaging applicaton, and I'm able to send messages (shown as the server client displays the message correctly) but then kicks my client off of the server. The server prints the following error:
java.io.EOFException at
java.io.ObjectInputStream$BlockDataInputStream.peekByte(UnknownSource)
at java.io.ObjectInputStream.readObject0(Unknown Source) at
java.io.ObjectInputStream.readObject(Unknown Source) at
com.liftedstarfish.lifte.gpschat0_2.Server$ClientThread.run(Server.java:243)
My Server Class:
public class Server {
// a unique ID for each connection
private static int uniqueId;
// an ArrayList to keep the list of the Client
private ArrayList<ClientThread> al;
// if I am in a GUI
private ServerGUI sg;
// to display time
private SimpleDateFormat sdf;
// the port number to listen for connection
private int port;
// the boolean that will be turned of to stop the server
private boolean keepGoing;
private String name;
/*
* server constructor that receive the port to listen to for connection as parameter
* in console
*/
public Server(int port, String name) {
this(port, name, null);
}
public Server(int port, String name, ServerGUI sg) {
// GUI or not
this.sg = sg;
// the port
this.port = port;
this.name = name;
// to display hh:mm:ss
sdf = new SimpleDateFormat("HH:mm:ss");
// ArrayList for the Client list
al = new ArrayList<ClientThread>();
}
public void start() {
keepGoing = true;
/* create socket server and wait for connection requests */
try
{
// the socket used by the server
ServerSocket serverSocket = new ServerSocket(port);
// infinite loop to wait for connections
while(keepGoing)
{
// format message saying we are waiting
display("Server waiting for Clients on " + name + ".");
Socket socket = serverSocket.accept(); // accept connection
// if I was asked to stop
if(!keepGoing)
break;
ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();
}
// I was asked to stop
try {
serverSocket.close();
for(int i = 0; i < al.size(); ++i) {
ClientThread tc = al.get(i);
try {
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE) {
// not much I can do
}
}
}
catch(Exception e) {
display("Exception closing the server and clients: " + e);
}
}
// something went bad
catch (IOException e) {
String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
display(msg);
}
}
/*
* For the GUI to stop the server
*/
protected void stop() {
keepGoing = false;
// connect to myself as Client to exit statement
// Socket socket = serverSocket.accept();
try {
new Socket("localhost", port);
}
catch(Exception e) {
// nothing I can really do
}
}
/*
* Display an event (not a message) to the console or the GUI
*/
private void display(String msg) {
String time = sdf.format(new Date()) + " " + msg;
if(sg == null)
System.out.println(time);
else
sg.appendEvent(time + "\n");
}
/*
* to broadcast a message to all Clients
*/
private synchronized void broadcast(String message) {
// add HH:mm:ss and \n to the message
String time = sdf.format(new Date());
String messageLf = time + " " + message + "\n";
// display message on console or GUI
if(sg == null)
System.out.print(messageLf);
else
sg.appendRoom(messageLf); // append in the room window
// we loop in reverse order in case we would have to remove a Client
// because it has disconnected
for(int i = al.size(); --i >= 0;) {
ClientThread ct = al.get(i);
// try to write to the Client if it fails remove it from the list
if(!ct.writeMsg(messageLf)) {
al.remove(i);
display("Disconnected Client " + ct.username + " removed from list.");
}
}
}
// for a client who logoff using the LOGOUT message
synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
/*
* To run as a console application just open a console window and:
* > java Server
* > java Server portNumber
* If the port number is not specified 1500 is used
*/
public static void main(String[] args) {
// start server on port 1500 unless a PortNumber is specified
int portNumber = 1500;
String serverName = "";
switch(args.length) {
case 1:
try {
portNumber = Integer.parseInt(args[0]);
}
catch(Exception e) {
System.out.println("Invalid port number.");
System.out.println("Usage is: > java Server [portNumber]");
return;
}
case 0:
break;
default:
System.out.println("Usage is: > java Server [portNumber]");
return;
}
// create a server object and start it
Server server = new Server(portNumber, serverName);
server.start();
}
public String getName()
{
return this.name;
}
/** One instance of this thread will run for each client */
class ClientThread extends Thread {
// the socket where to listen/talk
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
// my unique id (easier for deconnection)
int id;
// the Username of the Client
String username;
// the only type of message a will receive
ChatMessage cm;
// the date I connect
String date;
// Constructore
public ClientThread(Socket socket) {
// a unique id
id = ++uniqueId;
this.socket = socket;
/* Creating both Data Stream */
System.out.println("Thread trying to create Object Input/Output Streams");
try
{
// create output first
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
// read the username
username = (String) sInput.readObject();
display(username + " just connected.");
}
catch (IOException e) {
display("Exception creating new Input/output Streams: " + e);
return;
}
// have to catch ClassNotFoundException
// but I read a String, I am sure it will work
catch (ClassNotFoundException e) {
}
date = new Date().toString() + "\n";
}
// what will run forever
public void run() {
// to loop until LOGOUT
boolean keepGoing = true;
while(keepGoing) {
// read a String (which is an object)
try {
//Location of Error
>>>>>>>>>>>>>>>>>>>>cm = (ChatMessage) sInput.readObject();<<<<<<<<<<<<<<<<<
}
catch (IOException e) {
e.printStackTrace();
break;
}
catch(ClassNotFoundException e2) {
e2.printStackTrace();
break;
}
// the messaage part of the ChatMessage
String message = cm.getMessage();
// Switch on the type of message receive
switch(cm.getType()) {
case ChatMessage.MESSAGE:
broadcast(username + ": " + message);
break;
case ChatMessage.LOGOUT:
display(username + " disconnected with a LOGOUT message.");
keepGoing = false;
break;
case ChatMessage.WHOISIN:
writeMsg("List of the users connected at " + sdf.format(new Date()) + "\n");
// scan al the users connected
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
}
break;
case ChatMessage.ERROR:
broadcast(username + "> " + message);
break;
}
}
// remove myself from the arrayList containing the list of the
// connected Clients
remove(id);
close();
}
// try to close everything
private void close() {
// try to close the connection
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
/*
* Write a String to the Client output stream
*/
private boolean writeMsg(String msg) {
// if Client is still connected send the message to it
if(!socket.isConnected()) {
close();
return false;
}
// write the message to the stream
try {
sOutput.writeObject(msg);
}
// if an error occurs, do not abort just inform the user
catch(IOException e) {
display("Error sending message to " + username);
display(e.toString());
}
return true;
}
}
}
ChatMessage Class:
public class ChatMessage extends AppCompatActivity implements Serializable {
protected static final long serialVersionUID = 1112122200L;
// The different types of message sent by the Client
// WHOISIN to receive the list of the users connected
// MESSAGE an ordinary message
// LOGOUT to disconnect from the Server
static final int WHOISIN = 0, MESSAGE = 1, LOGOUT = 2, ERROR = 3;
private int type;
private String message;
// constructor
public ChatMessage(int type, String message) {
this.type = type;
this.message = message;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_message);
final TextView lblMessage = (TextView) findViewById(R.id.text_view_message);
if(type == MESSAGE)
lblMessage.setText(message);
}
// getters
public int getType() {
return type;
}
public String getMessage() {
return message;
}
}
From readObject documentation:
ClassNotFoundException - Class of a serialized object cannot be found.
InvalidClassException - Something is wrong with a class used by serialization.
StreamCorruptedException - Control information in the stream is inconsistent.
OptionalDataException - Primitive data was found in the stream instead of objects.
IOException - Any of the usual Input/Output related exceptions.
EOFException is a type of IOException, which is thrown when the end of the file is reached. All though this doesn't throw that particular error, it does throw IOException, meaning it can throw EOFException too.
So in your code, you simply add:
while(sInput.available() > 0){// > 0 means there are bytes to read.
//Read
}
This (in theory) avoids the EOFException. See this for reference
The peer has closed the connection. You should catch this exception separately, and break out of the loop when you catch it. At present you have no provision at all for this condtion.
Related
I am trying to develop a JavaFx application for testing an IPTV. And my task is checking of channel changing successfully. There is no any component or device at the moment. But I am searching for this task, after that I will buy.
My application will send some remote control command over the IR device.
Here is an IR device, but It doesn't have a Java API.
Is there a way for this solution?
I searched and found a device which name was RedRat. It is usb-infrared device that we can use it linux and windows OS.
There is a utility for using it with a programming language.
Here is a sample java code, may be useful for somebody. But you should have a redrat device.
First step, you have to download this redRatHub and paste a direction
secondly, run main class which has same path with redrathub folders.
public class MyDemo {
private static Client client;
private static String DEVICE_NAME = "";
private static String DATA_SET = "";
public static void main(String[] args) {
try {
startRedRat();
client = new Client();
client.openSocket("localhost", 40000);
DEVICE_NAME = client.readData("hubquery=\"list redrats\"").split("]")[1].split("\n")[0].trim();
DATA_SET = client.readData("hubquery=\"list datasets\"").split("\n")[1];
sendCommand("power");
TimeUnit.SECONDS.sleep(5);
sendCommand("btn1", "btn1", "btn1", "btn1");
sendCommand("btnOK");
TimeUnit.SECONDS.sleep(30);
sendCommand("btnBACK");
sendCommand("channel+");
sendCommand("btn6", "btn1");
sendCommand("channel+");
sendCommand("channel-");
sendCommand("volume+");
sendCommand("volume-");
sendCommand("power");
client.closeSocket();
p.destroy();
} catch (Exception ex) {
System.err.println(ex.getMessage());
} finally {
System.out.println("Finished. Hit <RETURN> to exit...");
}
}
private static void sendCommand(String... command) {
try {
for (String cmd : command) {
client.sendMessage("name=\"" + DEVICE_NAME + "\" dataset=\"" + DATA_SET + "\" signal=\"" + cmd + "\"");
TimeUnit.MILLISECONDS.sleep(500);
System.out.println(cmd + " signal send");
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void startRedRat() {
try {
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
p = Runtime.getRuntime().exec("cmd /C C:\\RedRatHub\\RedRatHubCmd.exe C:\\RedRatHub\\TivibuDB.xml");
return null;
}
};
worker.run();
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
this class is communicate with redrat device over the serial ports.
public class Client {
private Socket socket;
private DataOutputStream out;
private DataInputStream in;
/*
* Opens the socket to RedRatHubCmd.
*/
public void openSocket(String host, int port) throws UnknownHostException, IOException {
if (socket != null && socket.isConnected()) return;
socket = new Socket(host, port);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
}
/*
* Closes the RedRatHubCmd socket.
*/
public void closeSocket() throws IOException {
socket.close();
}
/*
* Sends a message to the readData() method. Use when returned data from RedRatHub is not needed.
*/
public void sendMessage(String message) throws Exception {
String res = readData(message);
if (!res.trim().equals("OK")) {
throw new Exception("Error sending message: " + res);
}
}
/*
* Reads data back from RedRatHub. Use when returned data is needed to be output.
*/
public String readData(String message) throws IOException {
if (socket == null || !socket.isConnected()) {
System.out.println("\tSocket has not been opened. Call 'openSocket()' first.");
return null;
}
// Send message
out.write((message + "\n").getBytes("UTF-8"));
// Check response. This is either a single line, e.g. "OK\n", or a multi-line response with
// '{' and '}' start/end delimiters.
String received = "";
byte[] inBuf = new byte[256];
while (true) {
// Read data...
int inLength = in.read(inBuf);
//byte[] thisMSg = new byte[inLength];
String msg = new String(Arrays.copyOfRange(inBuf, 0, inLength), "UTF-8");
received += msg;
if (checkEom(received)) return received;
}
}
/*
* Checks for the end of a message
*/
public boolean checkEom(String message) {
// Multi-line message
if (message.trim().endsWith("}")) {
return message.startsWith("{");
}
// Single line message
return message.endsWith("\n");
//return true;
}
}
I'm just getting into networking and I'm quite confused about how I can use a server from a server hosting company for a game. At the moment, the program allows a user to host the server from their computer and it works to some degree. The only problem is that when my friends connect to the game from other states their ping is super high and they lag horribly.
I'm now using a site that gives out free web hosting space. I've believe I've jumped through most of the permission hoops that I need in order to use sockets and the applet works just like it does while running on my computer.
Below is an excerpt from the Game class. If I use InetAddress.getLocalHost().getHostAddress() to get the IP, it gets the IP from the user who is using the client and makes them the server host. This works, but it doesn't solve my problem of lag.
Game.java
public synchronized void start() {
running = true;
thread = new Thread(this, NAME + "_main");
thread.start();
if (JOptionPane.showConfirmDialog(this, "Do you want to run the server") == 0) {
socketServer = new GameServer(this);
socketServer.start();
}
this.ipAddress = "31.170.163.198";
//this.ipAddress = InetAddress.getByName(ipAddress).toString();
System.out.println("IP: " + this.ipAddress);
socketClient = new GameClient(this, this.ipAddress);//Inet4Address.getLocalHost().getHostAddress());
try {
Player.setIp(Inet4Address.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
socketClient.start();
}
I want the server that contains the jar to host the server. We all ping test each other and we mostly all get timed out, however, when we ping the server's ip we all get decent ping. When I enter the Server's IP (I find this info in the control panel) manually the server/client fail to make a connection. I've tried using both the website IP and the server IP that are provided. I've also tried using the applet.getCodeBase().getHost() in order to retrieve the IP from the server but that IP failed to send/receive data as well.
Is what I'm trying to do possible? Is the server blocking me from using it in that way? Do I need to rewrite the whole program and look into java servlets to achieve my goal?
I apologize if the question is silly. I've been working on this for the past 3-4 days with very little progress. I've searched around a bit on using a server in this manner and I've found very little on the topic.
Below are some excerpts from other relevant pieces of code.
GameClient.java
package fraccas.java2dgame.net;
public class GameClient extends Thread {
private InetAddress ipAddress;
private DatagramSocket socket;
private Game game;
public long lastPing = 0;
public static int ping = 0;
public GameClient(Game game, String ipAddress) {
this.game = game;
try {
this.socket = new DatagramSocket();
this.ipAddress = InetAddress.getByName(ipAddress);
System.out.println("IP: " + InetAddress.getByName(ipAddress));
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
if (packet != null)
{
long current = System.currentTimeMillis();
ping = (int) (current - lastPing);
lastPing = current;
}
} catch (IOException e) {
e.printStackTrace();
}
this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
}
}
private void parsePacket(byte[] data, InetAddress address, int port) {
String message = new String(data).trim();
PacketTypes type = Packet.lookupPacket(message.substring(0, 2));
Packet packet = null;
switch (type) {
default:
case INVALID:
break;
case LOGIN:
packet = new Packet00Login(data);
handleLogin((Packet00Login) packet, address, port);
break;
case DISCONNECT:
packet = new Packet01Disconnect(data);
System.out.println("[" + address.getHostAddress() + ":" + port + "] "
+ ((Packet01Disconnect) packet).getUsername() + " has left the world...");
game.level.removePlayerMP(((Packet01Disconnect) packet).getUsername());
break;
case MOVE:
packet = new Packet02Move(data);
handleMove((Packet02Move) packet);
}
}
public void sendData(byte[] data) {
//if (!game.isApplet) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 3333);
try {
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
//}
}
private void handleLogin(Packet00Login packet, InetAddress address, int port) {
System.out.println("[" + address.getHostAddress() + ":" + port + "] " + packet.getUsername()
+ " has joined the game...");
PlayerMP player = new PlayerMP(game.level, packet.getX(), packet.getY(), packet.getUsername(), address, port);
game.level.addEntity(player);
}
private void handleMove(Packet02Move packet) {
this.game.level.movePlayer(packet.getUsername(), packet.getX(), packet.getY(), packet.getNumSteps(),
packet.isMoving(), packet.getMovingDir());
}
}
GameServer.java
package fraccas.java2dgame.net;
public class GameServer extends Thread {
private DatagramSocket socket;
private Game game;
private List<PlayerMP> connectedPlayers = new ArrayList<PlayerMP>();
public GameServer(Game game) {
this.game = game;
try {
this.socket = new DatagramSocket(3333);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
}
}
private void parsePacket(byte[] data, InetAddress address, int port) {
String message = new String(data).trim();
PacketTypes type = Packet.lookupPacket(message.substring(0, 2));
Packet packet = null;
switch (type) {
default:
case INVALID:
break;
case LOGIN:
packet = new Packet00Login(data);
System.out.println("[" + address.getHostAddress() + ":" + port + "] "
+ ((Packet00Login) packet).getUsername() + " has connected...");
PlayerMP player = new PlayerMP(game.level, 100, 100, ((Packet00Login) packet).getUsername(), address, port);
this.addConnection(player, (Packet00Login) packet);
break;
case DISCONNECT:
packet = new Packet01Disconnect(data);
System.out.println("[" + address.getHostAddress() + ":" + port + "] "
+ ((Packet01Disconnect) packet).getUsername() + " has left...");
this.removeConnection((Packet01Disconnect) packet);
break;
case MOVE:
packet = new Packet02Move(data);
this.handleMove(((Packet02Move) packet));
}
}
public void addConnection(PlayerMP player, Packet00Login packet) {
boolean alreadyConnected = false;
for (PlayerMP p : this.connectedPlayers) {
if (player.getUsername().equalsIgnoreCase(p.getUsername())) {
if (p.ipAddress == null) {
p.ipAddress = player.ipAddress;
}
if (p.port == -1) {
p.port = player.port;
}
alreadyConnected = true;
} else {
// relay to the current connected player that there is a new
// player
sendData(packet.getData(), p.ipAddress, p.port);
// relay to the new player that the currently connect player
// exists
//packet = new Packet00Login(p.getUsername(), p.x, p.y);
Packet00Login packetNew = new Packet00Login(p.getUsername(), p.x, p.y);
sendData(packetNew.getData(), player.ipAddress, player.port);
}
}
if (!alreadyConnected) {
this.connectedPlayers.add(player);
}
}
public void removeConnection(Packet01Disconnect packet) {
this.connectedPlayers.remove(getPlayerMPIndex(packet.getUsername()));
packet.writeData(this);
}
public PlayerMP getPlayerMP(String username) {
for (PlayerMP player : this.connectedPlayers) {
if (player.getUsername().equals(username)) {
return player;
}
}
return null;
}
public int getPlayerMPIndex(String username) {
int index = 0;
for (PlayerMP player : this.connectedPlayers) {
if (player.getUsername().equals(username)) {
break;
}
index++;
}
return index;
}
public void sendData(byte[] data, InetAddress ipAddress, int port) {
//if (!game.isApplet) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
this.socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
//}
}
public void sendDataToAllClients(byte[] data) {
for (PlayerMP p : connectedPlayers) {
sendData(data, p.ipAddress, p.port);
}
}
private void handleMove(Packet02Move packet) {
if (getPlayerMP(packet.getUsername()) != null) {
int index = getPlayerMPIndex(packet.getUsername());
PlayerMP player = this.connectedPlayers.get(index);
player.x = packet.getX();
player.y = packet.getY();
player.setMoving(packet.isMoving());
player.setMovingDir(packet.getMovingDir());
player.setNumSteps(packet.getNumSteps());
packet.writeData(this);
}
}
The applet does not have any errors in the console at the moment. It simply does not send/receive the data.
http://critterisland.bugs3.com/public_html/index.html (Applet Link)
http://gyazo.com/a91401545b1a741f2b9fc86471bd5762 (Image of Applet)
Thanks for you time,
Fraccas
The problem is that you're using a web host which is only able to provide the files to users as opposed to actually being able to run the software you've created.
To run your software independently in the way you're wanting, your easiest option is to rent a virtual private server (VPS) which is located appropriately for your users. However, you'll need to be able to do some basic configuration on the VPS (such as install Java), and then run your server as a console application.
Not much code needs to be changed to get it working. You could use the same jar file for both the server and the client by adding a command line argument which only starts the server (i.e. "-server"). From the server computer/VPS you would then start the server by running "java -jar CritterIslandTest.jar -server" which then only starts the server and handles communication. If the command line argument is not found you can then continue with the GUI logic.
I'm doing my assignment with Chat Server-client. Here is how i start server
public static void StartServer(){
// Create socket
try {
serversocket = new ServerSocket(ServerPort);
} catch (Exception e) {
isError = true;
ERRORCODE = "ERROR! Cannot create a new socket! " + e.getMessage();
return;
}
// A new thread to wait for connection
Thread TH_Wait4Connection = new Thread(){
public void run(){
while(true){
String ERRORHere = "-1"; // To specify whre the Errors are
try {
Connection = new Socket();
Connection = serversocket.accept();
} catch (Exception e) {
ERRORCODE = ERRORHere + " : " + e.getMessage();
return;
}
// Another Thread to handle a connection
try {
ERRORHere = "1";
Thread Client = new Thread(new ConnHandler(Connection));
ERRORHere = "2";
threadList.add(Client);
ERRORHere = "3";
Client.start();
ERRORHere = "4";
} catch (Exception e) {
ERRORCODE = ERRORHere + " : " + e.getMessage();
return;
}
try {Thread.sleep(10);} catch (Exception e) {}
} // End why loop
} // End run()
};
TH_Wait4Connection.start();
}
When i debug in eclipse, my clients can connect to server and everything is fine, server creates threads and no exception catched. But if i Run, it goes into the last catch and my ERRORCODE
ERRORCODE = ERRORHere + " : " + e.getMessage();
is
1 : 6 > 4
What are those errors? And how to fix it?
Thank for read.
Update class ConnHandler
public class ConnHandler implements Runnable{
public ConnHandler(Socket Connection) throws Exception{
InputStream IS = Connection.getInputStream();
byte[] InData = new byte[1024];
int bytesCount = IS.read(InData);
// Remove first 6 bytes
byte[] NewInData = Arrays.copyOfRange(InData, 6, bytesCount);
}
public void run(){}
}
Your problem is this line in ConnHandler:
byte[] NewInData = Arrays.copyOfRange(InData, 6, bytesCount);
When calling this line bytesCount is 4. Since argument FROM is bigger then argument TO (6 > 4), it throws an IllegalArgumentException. See here for more information about this method.
In general it is not advisable to catch the type Exception instead of the subtypes in different catch-blocks. Your current implementation could hide unchecked Exceptions. Further if you catch the subtypes, you will know what type occurred (without manually checking) and debug faster, like in your current case.
Why is this code nott accumulating many clients?
I'm new to java.
It only runs for only 1 client.
Can anyone explain why it doesn't support multiple clients for socket programming?
import java.net.*;
import java.io.*;
/**
* Demo Server: Contains a multi-threaded socket server sample code.
*/
public class ServerDemo extends Thread
{
final static int _portNumber = 5559; //Arbitrary port number
public static void main(String[] args)
{
try {
new ServerDemo().startServer();
} catch (Exception e) {
System.out.println("I/O failure: " + e.getMessage());
e.printStackTrace();
}
}
public void startServer() throws Exception {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(_portNumber);
} catch (IOException e) {
System.err.println("Could not listen on port: " + _portNumber);
System.exit(-1);
}
while (listening) {
handleClientRequest(serverSocket);
}
serverSocket.close();
}
private void handleClientRequest(ServerSocket serverSocket) {
try {
new ConnectionRequestHandler(serverSocket.accept()).run();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Handles client connection requests.
*/
public class ConnectionRequestHandler implements Runnable{
private Socket _socket = null;
private PrintWriter _out = null;
private BufferedReader _in = null;
public ConnectionRequestHandler(Socket socket) {
_socket = socket;
}
public void run() {
System.out.println("Client connected to socket: " + _socket.toString());
try {
_out = new PrintWriter(_socket.getOutputStream(), true);
_in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
String inputLine, outputLine;
BusinessLogic businessLogic = new BusinessLogic();
outputLine = businessLogic.processInput(null);
_out.println(outputLine);
//Read from socket and write back the response to client.
while ((inputLine = _in.readLine()) != null) {
outputLine = businessLogic.processInput(inputLine);
if(outputLine != null) {
_out.println(outputLine);
if (outputLine.equals("exit")) {
System.out.println("Server is closing socket for client:" + _socket.getLocalSocketAddress());
break;
}
} else {
System.out.println("OutputLine is null!!!");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally { //In case anything goes wrong we need to close our I/O streams and sockets.
try {
_out.close();
_in.close();
_socket.close();
} catch(Exception e) {
System.out.println("Couldn't close I/O streams");
}
}
}
}
/**
* Handles business logic of application.
*/
public static class BusinessLogic {
private static final int LoginUserName = 0;
private static final int LoginPassword = 1;
private static final int AuthenticateUser = 2;
private static final int AuthSuccess = 3;
private int state = LoginUserName;
private String userName = null;
private String userPassword = null;
public String processInput(String clientRequest) {
String reply = null;
try {
if(clientRequest != null && clientRequest.equalsIgnoreCase("login")) {
state = LoginPassword;
}if(clientRequest != null && clientRequest.equalsIgnoreCase("exit")) {
return "exit";
}
if(state == LoginUserName) {
reply = "Please Enter your user name: ";
state = LoginPassword;
} else if(state == LoginPassword) {
userName = clientRequest;
reply = "Please Enter your password: ";
state = AuthenticateUser;
} else if(state == AuthenticateUser) {
userPassword = clientRequest;
if(userName.equalsIgnoreCase("John") && userPassword.equals("doe")) {
reply = "Login Successful...";
state = AuthSuccess;
} else {
reply = "Invalid Credentials!!! Please try again. Enter you user name: ";
state = LoginPassword;
}
} else {
reply = "Invalid Request!!!";
}
} catch(Exception e) {
System.out.println("input process falied: " + e.getMessage());
return "exit";
}
return reply;
}
}
}
You are not starting the thread in your code.
instead of
new ConnectionRequestHandler(serverSocket.accept()).run();
call
new Thread(new ConnectionRequestHandler(serverSocket.accept())).start();
method run() of your Runnable class will be invoked when you start your thread, you should not call this run() method directly.
Instead of that you should make a thread instance via
Thread myThread = new Thread(aRunnableInstance);
and start it:
myThread.start();
You're not starting a new thread, but simply running the RequestHandler code in the main thread.
Look up the difference between Thread.start() and Runnable.run(). This question might help.
Edit:
You're just missing the part where you would tell the JVM to create a new Thread to execute your Runnable code. Without a call to Thread.start() your current (and only) thread would be busy handling one request at a time. You want one Thread per request, basically. There are more advanced ways of doing this (thread pools and whatnot), but this should get you started.
private void handleClientRequest(ServerSocket serverSocket) {
try {
new Thread(ConnectionRequestHandler(serverSocket.accept())).start();
} catch (IOException e) {
e.printStackTrace();
}
}
I'm developing an Android application (client) and want it to connect with my Java server using TCP communication, and so far everything is going well.
Server Code:
import java.net.*;
import java.io.*;
import globalvariables.GlobalVariables;
import interface_package.ServerInterface;
import java.util.Timer;
/**
*
* #author wsserver
*/
public class ThreadedAndroidServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
GlobalVariables.init();
//Prevzemi staticen interface
GlobalVariables.sinterface = new ServerInterface();
GlobalVariables.sinterface.show();
//INFINITE LOOP
while(true)
int port = GlobalVariables.portNo;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server has started listening on port " + port);
GlobalVariables.sinterface.setServerStatus("Server has started listening on port " + port);
} catch (IOException e) {
System.out.println("Error: Cannot listen on port " + port + " : " + e);
GlobalVariables.sinterface.setServerStatus("Error: Cannot listen on port " + port + " : " + e);
System.exit(1);
}
while (true) // infinite loop - loops once for each client
{
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept(); //waits here (forever) until a client connects
System.out.println("Server has just accepted socket connection from a client");
GlobalVariables.sinterface.setServerStatus("Server has just accepted socket connection from a client");
} catch (IOException e) {
System.out.println("Accept failed: " + e);
GlobalVariables.sinterface.setServerStatus("Accept failed: " + e);
break;
}
// Create the Handle Connection object - our new thread object - only create it
ThreadedHandleConnection con = new ThreadedHandleConnection(clientSocket);
if (con == null) //If it failed send and error message
{
try {
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
os.writeObject("error: Cannot open socket thread");
os.flush();
os.close();
} catch (Exception ex) //failed to even send an error message
{
System.out.println("Cannot send error back to client: " + ex);
GlobalVariables.sinterface.setServerStatus("Cannot send error back to client: " + ex);
}
} else {
con.start();
} // otherwise we have not failed to create the HandleConnection object
// start this thread now
}
try // do not get here at the moment
{
System.out.println("Closing server socket.");
GlobalVariables.sinterface.setServerStatus("Closing server socket.");
serverSocket.close();
} catch (IOException e) {
System.err.println("Could not close server socket. " + e.getMessage());
GlobalVariables.sinterface.setServerStatus("Could not close server socket. " + e.getMessage());
}
}
}
Connection Handler:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tcpServer_package;
import java.net.*;
import java.io.*;
import java.util.*;
import busimesslogic_package.Functions;
/**
*
* #author wsserver
*/
public class ThreadedHandleConnection extends Thread {
private Socket clientSocket; // Client socket object
private ObjectInputStream is; // Input stream
private ObjectOutputStream os; // Output stream
// The constructor for the connecton handler
public ThreadedHandleConnection(Socket clientSocket) {
this.clientSocket = clientSocket;
}
// The main thread execution method
public void run() {
try {
this.is = new ObjectInputStream(clientSocket.getInputStream());
this.os = new ObjectOutputStream(clientSocket.getOutputStream());
while (this.readCommand()) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Receive and process incoming command from client socket
private boolean readCommand() {
String wholeCommand = null;
try {
wholeCommand = (String) is.readObject();
} catch (Exception e) {
wholeCommand = null;
}
if (wholeCommand == null) {
this.closeSocket();
return false;
}
System.out.println("Received: "+wholeCommand);
//GET COMMAND PARAMETARS
String[] commParams = wholeCommand.split(";");
//GET COMMAND TYPE
int type = Integer.parseInt(commParams[0]);
//SELECT COMMAND PROCEDURE
Functions functions = new Functions();
String IPaddress = clientSocket.getRemoteSocketAddress().toString();
IPaddress = IPaddress.substring(IPaddress.indexOf("/")+1, IPaddress.indexOf(":"));
switch (type) {
case 1: {
String sendText = getTextToSend();
send(sendText);
break;
}
default:{
sendError("0;"+wholeCommand);
break;
}
}
System.gc();
return true;
}
// Send a message back through to the client socket as an Object
private void send(Object o) {
try {
System.out.println("Sending " + o);
this.os.writeObject(o);
this.os.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
// Send a pre-formatted error message to the client
public void sendError(String msg) {
this.send("error:" + msg); //remember a string IS-A object!
}
// Close the client socket
public void closeSocket() //close the socket connection
{
try {
this.os.close();
this.is.close();
this.clientSocket.close();
} catch (Exception ex) {
System.err.println(ex.toString());
}
}
}
Android Client Code:
package com.example.zpbitolaoperator;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import android.util.Log;
public class TCPClient{
//Comunication variables
private static Socket socket;
private static ObjectOutputStream os;
private static ObjectInputStream is;
//Server parametars
static String serverIP;
static int port;
//Communication status
static boolean connectionStatus = false;
public static boolean connectToServer() {
try // open a new socket to port: and create streams
{
serverIP = GlobalVariables.serverIP;
port = GlobalVariables.portNo;
socket = new Socket(serverIP, port);
os = new ObjectOutputStream(socket.getOutputStream());
is = new ObjectInputStream(socket.getInputStream());
Log.d("DEBUG", "Connected to Server");
connectionStatus = true;
return true;
} catch (Exception ex) {
Log.d("DEBUG", "Failed to Connect to Server " +ex.toString(), ex.getCause());
connectionStatus = false;
return false;
}
}
public static boolean closeConnection(String message){
try{
socket.close();
Log.d("DEBUG", "Closed connection to Server");
return true;
} catch (Exception ex){
Log.d("DEBUG", "Failed to close connection to Server " +ex.toString(), ex.getCause());
return false;
}
}
private static String sendMessage(String message) {
String returnString;
send(message);
returnString = (String) receive();
if (returnString != null) {
Log.d("DEBUG", "Server returned: " + returnString);
}else{
return returnString = "ERROR";
}
return returnString;
}
// method to send a generic object.
private static void send(Object o) {
try {
Log.d("DEBUG", "Sending: " + o);
os.writeObject(o);
os.flush();
} catch (Exception ex) {
Log.d("DEBUG", "Sending to server " +ex.toString(), ex.getCause());
}
}
// method to receive a generic object.
private static Object receive() {
Object o = null;
try {
o = is.readObject();
} catch (Exception ex) {
Log.d("DEBUG", "Receive from server " +ex.toString(), ex.getCause());
}
return o;
}
/**
* Isprakja poraka do server
* #param message
* #return ili ERROR ili poraka
*/
public synchronized static String sendToServer(String message) {
String rez = "";
try {
rez = sendMessage(message);
} catch (Exception ex) {
Log.d("DEBUG", "Send to server " +ex.toString(), ex.getCause());
}
return rez;
}
public static boolean getCommunicationStatus(){
return connectionStatus;
}
}
I am sending String data to my server (comand;param1;param2....), the server proces that data and returns some data do the android application. The android application is the TCP Client and the java application is the server. For every connection the server creates thread (infinite) that handles that connection. The problem is that my server cant send something without the client sending the request first. The ObjectInputStream readObject() blocks the thread until the client send some data. I want to use the same socket to send in the other direction (java -> android and the android application send some data back) .I know that this can be done by opening another socket where the Android will be the server and the java application will be the client. Is this posible and how?
If you want to be able to concurrently receive data from a client and send data to the client then you'll have to either use two threads per client (one to receive and one to send) or use non-blocking IO.