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.
Related
I'm developing a net game with udp socket (DatagramSocket) between two clients (the server notifies both the respective ip and the clients establish the connection). The problem is that the connection isn't working on all PCs. It works for some friends, but doesn't work for others. Denifitely the problem is sending.
Send hi is a function to send a sort message repeatedly to start the port (I discovered that to receive in UDP port it's necessary to send first), and send ack it just a confirmation to the "hi"
(There is a process calling receive, and obviously i send and receive in the same port)
This would be the most important:
public class connection {
protected DatagramSocket socketUDP;
protected InetAddress address;
protected int timeout = 50;
protected int portSend;
protected byte[] bufReceive = new byte[65535];
protected byte[] bufSend;
private boolean isUDP = true;
public connection(String ip, int port, int timeout, boolean isUDP) {
this.isUDP = isUDP;
this.timeout = timeout;
try {
if(isUDP) {
socketUDP = new DatagramSocket(port);
this.portReceive = port;
if (timeout > 0) {
socketUDP.setSoTimeout(timeout);
}
address = InetAddress.getByName(ip);
}
else{
///
}
}catch (Exception e){
e.printStackTrace();
}
this.rec = new receiver(this);
this.rec.start();
}
private void send(int id, Object msg, boolean string){
if(isUDP) {
bufSend = (Integer.toString(id) + ";NR;" + (String)msg).getBytes();
DatagramPacket packet = new DatagramPacket(bufSend, bufSend.length, address, portSend);
try {
socketUDP.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
else {
/////
}
}
public void receive(){
if(blockReception || socketUDP != null && !socketUDP.isConnected()){return;}
try {
if(isUDP) {
String received = "";
DatagramPacket packet
= new DatagramPacket(bufReceive, bufReceive.length);
socketUDP.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
received = new String(packet.getData(), 0, packet.getLength());
if(received.equals("HI")){
sendAck(msgID.toClient.hi);
return;
}
System.out.println(received)
}
else{
//////
}
}catch (Exception e){e.printStackTrace();}
}
public void setPortSend(int portSend) {
this.portSend = portSend;
if(isUDP) {
socketUDP.connect(address, portSend);
sendHi();
}
}
}
I hope someone can say me why it isn't working for all users.
Most personal firewalls or antiviruses are blocking UDP inbound traffic. Business and education organizations are often blocking UDP other than for some common services. Some ISP s may also be blocking UDP traffic on unusual ports.
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.
i am developing web application and i host it in tomcat server. my requirement is client system wants to know the ip address of the system where the tomcat server located in a network.Before make any request to the server using java.or any possible to set default ip address for the tomcat server.and how can i use the default ip address to make a request if system ip and tomcat ip are different.
I don't know if I understood your question right. So the server is running in a local area network and your client software does not know which address/ip to connect to? You could add a multicast server to your servers app and a multicast receiver to your clients. The server will send a boardcast packet frequently to a specified boardcast address/channel, i.e. 203.0.113.0.
Once your client starts, it will receive the boardcast packet send by the server, as long as he is connected to the same channel. The packet is containing the servers address. You can than use that address to connect to the server.
Update
This is a very simplyfied example of a sender, receiver and a constants class to share the settings. It sends a String (Server is here) as packet data, but in a real world application, you should create an object serialize it at the server and deserialize it at the client. That object could hold more information about the server an could be verified at client side.
Server/Client side shared code:
public final class MulticastConstants {
public static final String MULTICAST_PACKET_DATA = "Server is here!";
public static final String MULTICAST_CHANNEL = "230.0.0.1";
public static final int MULTICAST_PORT = 8881;
public static final int MULTICAST_PACKET_SIZE = MULTICAST_PACKET_DATA.getBytes().length;
}
Server Side code:
The sender is a WebListener and will start and stop with your application.
#WebListener
public class MulticastSender implements ServletContextListener {
private MulticastSocket socket;
private boolean running = true;
private Thread mcss;
public MulticastSender() {
System.out.println("New " + this.getClass().getSimpleName());
try {
socket = new MulticastSocket(MulticastConstants.MULTICAST_PORT);
mcss = new MulticastServerThread();
} catch (IOException e) {
System.out.println("Error creating MulticastSender: " + e.getMessage());
}
}
#Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Starting " + this.getClass().getSimpleName());
mcss.start();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Stopping " + this.getClass().getSimpleName());
this.running = false;
socket.disconnect();
socket.close();
}
private class MulticastServerThread extends Thread {
public MulticastServerThread() {
super("MulticastServer");
}
public void run() {
System.out.println("Start sending multicast packets ...");
while (running) {
System.out.println("Sending multicast packet ...");
try {
byte[] dataBuffer = MulticastConstants.MULTICAST_PACKET_DATA.getBytes();
InetAddress group = InetAddress.getByName(MulticastConstants.MULTICAST_CHANNEL);
DatagramPacket packet = new DatagramPacket(dataBuffer, dataBuffer.length, group, MulticastConstants.MULTICAST_PORT);
socket.send(packet);
System.out.println("Packet send ...");
try {
sleep(2000);
} catch (InterruptedException e) {
}
} catch (IOException e) {
System.out.println("Error sending multicast packet: " + e.getMessage());
running = false;
break;
}
}
socket.close();
}
}
}
Client side code:
The client only receives a single packet for simplicity. You might create a thread to not to freeze your clients gui.
public class MulticastReceiver {
private MulticastSocket socket;
private InetAddress address;
public static void main(String[] args) throws InterruptedException {
new MulticastReceiver();
}
public MulticastReceiver() {
System.out.println("Starting MulticastReceiver ...");
try {
address = InetAddress.getByName(MulticastConstants.MULTICAST_CHANNEL);
socket = new MulticastSocket(MulticastConstants.MULTICAST_PORT);
socket.joinGroup(address);
DatagramPacket packet;
try {
byte[] buf = new byte[MulticastConstants.MULTICAST_PACKET_SIZE];
packet = new DatagramPacket(buf, buf.length);
System.out.println("Waiting for packets ...");
socket.receive(packet);
System.out.println("Received a packet (" + packet.getLength() + " bytes) ...");
// deserialize packet.getData() to your own object (for simplicity a String is used) ...
// check if type and serialVersionId are ok, otherwise dispose packet ...
System.out.println("Server is located at: " + packet.getAddress());
socket.close();
// connect to server ...
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
} catch (UnknownHostException e) {
System.out.println("Could not connect to host \"" + address + "\": " + e.getMessage());
} catch (Exception e) {
System.out.println("Error initializing: " + e.getMessage());
}
}
}
Tested on Glassfish 4, hope that helps.
Given this:
. . .
ServerSocket serverSocket = new ServerSocket(1111);
while (helperSockets.size() < Common.NUM_HELPERS) {
Socket helperSocket = serverSocket.accept();
. . .
This throws the exception:
new Socket("localhost", 1111, InetAddress.getLocalHost(), localPort);
Exception:
java.net.ConnectException: connect: Address is invalid on local machine, or port is not valid on remote machine
I'm trying to use this constructor to set the local port, so what am I doing wrong? Source below.
The constructor creates a thread that listens for clients via ServerSockets, while trying to connect to other clients. This client tries to connect with itself for testing. The problem is encountered upon first iteration of the for loop.
public class DisSemHelper extends Thread {
private int id;
private int semaphore;
private Clock clock;
private Vector<Socket> helperSockets;
private int localPort;
private int receivedSender;
private String receivedOperation;
private int receivedTimestamp;
/**
*/
public DisSemHelper(int id) {
this.id = id;
this.semaphore = 0;
this.clock = new Clock();
this.helperSockets = new Vector<Socket>();
this.receivedSender = -1;
this.receivedOperation = null;
this.receivedTimestamp = -1;
this.localPort = Common.portMap.get(id);
new ConnectionListener().start();
/* Create and store connections to all helpers */
for (int i=0; helperSockets.size() < Common.NUM_HELPERS; i++) {
Socket helperSocket = null;
// String portKey = "STREET_" + i;
/* Wait until target street socket is ready. Retry every second. */
Exception e = new ConnectException();
while (helperSocket == null) {
try {
Thread.sleep(1000);
helperSocket = new Socket("localhost", 2222, InetAddress.getLocalHost(), localPort);
} catch (ConnectException ce) {
e = ce;
e.printStackTrace();
} catch (UnknownHostException uhe) {
uhe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException ie) {
e.printStackTrace();
}
}
int remotePort = helperSocket.getPort();
int connectedHelperID = Common.portMap.indexOf(remotePort);
if (this.helperSockets.size() <= connectedHelperID) {
this.helperSockets.add(helperSocket);
System.out.println("Helper " + id + " added socket from outgoing: local port: " + helperSocket.getLocalPort() + " remote port: " + helperSocket.getPort());
}
}
System.out.println(this.helperSockets);
}
private class ConnectionListener extends Thread {
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(2222);
/* Listen for connections from other helpers */
while (helperSockets.size() < Common.NUM_HELPERS) {
Socket helperSocket = serverSocket.accept();
// TODO Will indexof int in list of Integers work?
int remotePort = helperSocket.getPort();
int connectedHelperID = Common.portMap.indexOf(remotePort);
// TODO Does this really work?
if (connectedHelperID == -1) {
helperSockets.add(helperSocket);
System.out.println("Helper " + id + " added socket from incoming: local port: " + helperSocket.getLocalPort() + " remote port: " + helperSocket.getPort());
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is a WAG, but I'd try the other constructors in Socket.
Try new Socket(INetAddress.getLocalHost(), "111");
See:
http://ashishmyles.com/tutorials/tcpchat/index.html
Can you make a simple test-case and post the source? That'll help us troubleshoot this better.
new Socket("localhost", 1111, InetAddress.getLocalHost(), localPort);
What exactly are you trying to do here? Why do you need to define what local host/port pair to use locally? A client should normally just specify the remote host/port and let the OS pick the local port. This is perhaps the problem.
Not a true solution, but I ended up working around setting the local port (because nobody seems to like that idea).
i'm working with an example of client-server programm on Java. I faced such a problem:
I start the server with 8080 port and a localhost, than I start a client and make a request. As soon as the request done both programms close theri sockets, so i can't repeat my actions. How can i use the same client and the same server to make more than one request?
public class Network extends Thread
{
MasterEdit ME = new MasterEdit();
private Socket _socket;
InputStream is; //Data streams
OutputStream os;
/**
* Network class constructor
*/
public Network(int port, int backlog, InetAddress address)
{
//We create an object of SocketFactory
SocketFactory sf = new SocketFactory();
//Save server socket
ServerSocket ss = null;
try
{
if(address == null) //If there is no host
{
if(backlog <= 0) //If backlog is not given we create it with port
{ ss = sf.createServerSocket(port);
System.out.println("Success");
}
else
ss = sf.createServerSocket(port, backlog); //If backlog is given we just create it
}
else
ss = sf.createServerSocket(port, backlog, address); //If everything is given we create it using data
}
catch(Exception e)
{
//Exception with creation of socket
System.err.println("Failed open server socket");
System.exit(1); //Stop program and send 1 as a exception-code
}
while(true) //Listening to the socket
{
try
{
StartThread(ss.accept()); //If client has connected we send him to the daemon
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
/**
* Start daemon-tool when client has connected
*/
private void StartThread(Socket ss)
{
_socket = ss; //initializing of global variable
setDaemon(true); //anounce that new potok is daemon
setPriority(NORM_PRIORITY); //set the priority
start(); //Start it
}
#Override
public void run()
{
byte buffer[] = new byte[64*1024]; //buffer in 64 kb
try
{
is = _socket.getInputStream();
os = _socket.getOutputStream(); //Initializing the output stream to a client
String toClient = SearchRequest(new String(buffer, 0, is.read(buffer)));
os.write(toClient.getBytes()); //Sending an answer
}
catch(Exception e)
{
e.printStackTrace();
}
}
private String SearchRequest(String request)
{
String info = ""; //Initializing of a variable
if(request.equalsIgnoreCase("info")) //Check the request
{
//Adding data
info += "Virtual Machine Information (JVM)n";
info += "JVM Name: " + System.getProperty("java.vm.name")+"n";
info += "JVM installation directory: " + System.getProperty("java.home")+"n";
info += "JVM version: " + System.getProperty("java.vm.version")+"n";
info += "JVM Vendor: " + System.getProperty("java.vm.vendor")+"n";
info += "JVM Info: " + System.getProperty("java.vm.info")+"n";
return info; //Give the answer
}
if(request.charAt(0)=='0') {
StringTokenizer rm = new StringTokenizer(request, " \t\n\r,:");
rm.nextToken();
ME.MasterDell(Double.parseDouble(rm.nextToken()), Double.parseDouble(rm.nextToken()), Double.parseDouble(rm.nextToken()), Double.parseDouble(rm.nextToken()));
return "Successfully deleted";
}
if(request.charAt(0)=='1'){
StringTokenizer temp = new StringTokenizer(request, " \t\n\r,:");
temp.nextToken();
ME.MasterAdd(Double.parseDouble(temp.nextToken()), Double.parseDouble(temp.nextToken()), Double.parseDouble(temp.nextToken()), Double.parseDouble(temp.nextToken()), Double.parseDouble(temp.nextToken()), Double.parseDouble(temp.nextToken()), temp.nextToken());
return "Successfully added";
}
this.ClostIt();
return "Bad request"; //bad request
}
public void ClostIt() {
try {
is.close();
os.close();
_socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
It's server part. It usess SocketFactory class but mainly it just creates a socket in the begining. In main programm i call new Network(PORT, BACKLOG, InetAddress.getByName(host));
I am guessing in your server program you don't have a loop but rather something like this:
public static void main( String args[] ) {
ServerSocket server = new ServerSocket(...);
Socket con = server.accept();
//process the client connection ...
//done, exit!
}
rather than
public static void main( String args[] ) {
ServerSocket server = new ServerSocket(...);
Socket con = null;
while( condition /* e.g. shutdown server message received */ ) {
con = server.accept();
//process the client connection ...
//then keep waiting for the next request
}
//done, exit!
}
Bear in mind the above sample only processes one client at a time! you will need to step into multi-threading for processing simultaneous clients.
This is a good starter for a multi threaded server
http://www.kieser.net/linux/java_server.html
Mark