I recently started learning networking with sockets in java. So i've created a multiplayer game that is playable on the same computer but i wanted to make it network-multiplayer, then i learned about sockets, now, i want to send the variables of the position of the player in the game to a server which then can place that player in that position in the other game instance running on a different machine. And the thing is, i just fail at it and all the data doesnt get received or read. I also want the position to get sent and received constantly which is also a problem for me...
I tried using ObjectOutputStream and ObjectInputStream to send a int array with the variables but that also failed, so could you please show me how to do this, because i have no idea and i cant seem to find an answer online.
Thx
As the easiest solution, use the Object Streams to send an object created by you where you store these coordinates, but this class must implement Serializable interface. For example for 2d coordinates:
class Coords implements Serializable {
int x, y;
public Coords(int x, int y) {
this.x = x;
this.y = y;
}
}
...
// To write:
// oos = ObjectOutputStream of the socket
Coords tmp = new Coords(x, y);
oos.writeObject(tmp);
oos.flush();
...
//To read:
//ois = ObjectInputStream of the socket
Coords tmp = (Coords)ois.readObject();
http://java.sun.com/developer/technicalArticles/ALT/sockets/ can also aid you.
try something like this:
import java.io.*;
import java.net.*;
class Server extends Thread {
Server() throws IOException {
serverSocket = new ServerSocket(0);
}
public void run() {
while (true) {
try {
Socket client = serverSocket.accept();
Connect c = new Connect(client);
c.start();
} catch (Exception e) {}
}
}
final ServerSocket serverSocket;
}
class Data implements Serializable {
int[] data = { 1, 2, 3 };
}
class Connect extends Thread {
public Connect(Socket clientSocket) {
client = clientSocket;
try {
ois = new ObjectInputStream(client.getInputStream());
oos = new ObjectOutputStream(client.getOutputStream());
} catch (Exception e1) {
try {
client.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return;
}
}
public void run() {
try {
oos.writeObject(new Data());
oos.flush();
ois.close();
oos.close();
client.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("done");
}
final Socket client;
ObjectInputStream ois;
ObjectOutputStream oos;
}
class Client {
Client(int port) {
this.port = port;
}
void connectAndRead() {
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
Socket socket = null;
Data data = null;
try {
socket = new Socket("127.0.0.1", port);
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
data = (Data) ois.readObject();
oos.close();
ois.close();
for (int d : data.data)
System.out.println(d);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
final int port;
}
public class Main {
public static void main(String[] arguments) throws IOException, InterruptedException {
Server server = new Server();
server.start();
Client client = new Client(server.serverSocket.getLocalPort());
client.connectAndRead();
}
}
Related
I want to send some objects using network. My network I made it using DatagramSocket, DatagramPacket, ByteArrayInputStream, ObjectInputStream, ByteArrayOutputStream and ObjectOutputStream.
When I was trying to send an object using network I got java.io.EOFException and when I handled this exception using try and catch I lost my object.
Server Side
public class GameServer extends Thread {
private DatagramSocket socket;
private DatagramPacket packet;
private byte[] data;
private ByteArrayInputStream bais;
private ObjectInputStream ois;
private ByteArrayOutputStream baos;
private ObjectOutputStream oos;
private Game game;
public GameServer() {
try {
this.socket = new DatagramSocket(1331);
}
catch (SocketException e) {
e.printStackTrace();
}
start();
}
#Override
public void run() {
while (true) {
data = new byte[6400];
packet = new DatagramPacket(data, data.length);
Object object = receive();
if (object instanceof String) {
String message = (String) object;
System.out.println("CLIENT [ " + packet.getAddress().getHostAddress() + " : " + packet.getPort() + " ] >> " + message.trim());
if (message.equalsIgnoreCase("start")) {
game = new Game("Tankies", 1200, 700);
sendObject(game);
}
}
else if (object instanceof State) {
System.out.println("got state");
}
else if (object instanceof Player)
System.out.println("hi player");
}
}
private Object receive() {
bais = new ByteArrayInputStream(data);
try {
socket.receive(packet);
ois = new ObjectInputStream(new BufferedInputStream(bais));
return ois.readObject();
} catch (EOFException e) {
System.out.println("SERVER Got EOFException");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private void sendData(byte[] data, InetAddress ipAddress, int port) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
this.socket.send(packet);
}
catch (IOException e) {
e.printStackTrace();
}
}
private void sendObject(Object object) {
baos = new ByteArrayOutputStream(6400);
oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
}
catch (IOException e) {
e.printStackTrace();
}
sendData(baos.toByteArray(), packet.getAddress(), packet.getPort());
}
}
Client Side
public class GameClient extends Thread implements Serializable {
private InetAddress ipAddress;
private transient DatagramSocket socket;
private transient DatagramPacket packet;
private byte[] data;
private transient ByteArrayInputStream bais;
private transient ObjectInputStream ois;
private transient ByteArrayOutputStream baos;
private transient ObjectOutputStream oos;
private Game game;
public GameClient(String ipAddress) {
try {
this.socket = new DatagramSocket();
}
catch (SocketException e) {
e.printStackTrace();
}
try {
this.ipAddress = Inet4Address.getByName(ipAddress);
}
catch (UnknownHostException e) {
e.printStackTrace();
}
start();
}
#Override
public void run() {
while (true) {
data = new byte[6400];
packet = new DatagramPacket(data, data.length);
Object object = receive();
if (object instanceof String) {
System.out.println("SERVER >> " + object);
}
else if (object instanceof Game) {
this.game = (Game) object;
this.game.setClient(this);
this.game.start();
}
}
}
private Object receive() {
bais = new ByteArrayInputStream(data);
try {
socket.receive(packet);
ois = new ObjectInputStream(new BufferedInputStream(bais));
return ois.readObject();
}
catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private void sendData(byte[] data) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331);
try {
this.socket.send(packet);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void sendObject(Object object) {
baos = new ByteArrayOutputStream(6400);
oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
}
catch (IOException e) {
e.printStackTrace();
}
sendData(baos.toByteArray());
}
}
Code to send the object to server
public class MultiplayerState extends State{
private World world;
private Tank myTank, playerTank;
public MultiplayerState(Handler handler) {
super(handler);
}
#Override
public void startState() {
world = new World(handler,"res/worlds/world1.txt");
handler.setWorld(world);
myTank = new Tank(handler, world.getSpawnX(), world.getSpawnY());
handler.getGame().getRender().addObject(world);
handler.getGame().getRender().addObject(myTank);
world.start();
myTank.start();
handler.getGame().getClient().sendObject(handler.getGame().getPlayer());
}
}
handler.getGame().getClient().sendObject(handler.getGame().getPlayer());
This line to send player to server .. some explanation about code .. this is a game using multithreading in java and i want to create simple network to make two different laptops playing this game online because of that i made this network. I created class Handler this is a class to manage all the game, using object instance of Handler class I can get anything in the game and I want to get object instance of Player class to send it to server because I want to do something to make the game online.
I solved this exception by made GameClient object in Game class transient because I don't want to serialize it. What I want is to use this object to send something to server from Game object internally.
I want to check what type of object is sent to the server as there are two types of clients sending object, one which is a Car Driver and another which is a pedestrian. But whenever I use the if(datain.readObject() instanceof Pedestrian or CarDriver) the server doesn't receive any object and no response is sent to the client anymore. Here is my code:
Server
package eece350;
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Scanner;
import java.lang.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.*;
/**
*
* #author user
*/
public class SkillsServer {
private ServerSocket serverSocket;
private void acceptConnections() {
try {
int port = 7171;
serverSocket = new ServerSocket(port);
}
catch (IOException e)
{
System.err.println("ServerSocket instantiation failure");
e.printStackTrace();
System.exit(0);
}
// Entering the infinite loop
while (true) {
try {
// wait for a TCP handshake initialization (arrival
of a "SYN"
// packet)
Socket newConnection = serverSocket.accept();
System.out.println("accepted connection");
// Now, pass the connection socket created above to a thread and
// run it in it
// First create the thread and pass the connection socket to it
// This is a non-blocking function: constructor of the class
// ServerThread
ServerThread st = new ServerThread(newConnection);
// Then, start the thread, and go back to waiting for another
// TCP connection
// This also is not blocking
new Thread(st).start();
}
catch (IOException ioe)
{
System.err.println("server accept failed");
}
}
}
public static void main(String[] args) throws NullPointerException,
ClassNotFoundException, FileNotFoundException, SQLException
{
SkillsServer server = null;
server= new SkillsServer();
// call this function, which will start it all...
server.acceptConnections();
}
// Internal class
class ServerThread implements Runnable
{
private Socket socket;
private ObjectInputStream datain;
private ObjectOutputStream dataout;
private DataOutputStream outToClient;
ServerThread(Socket socket)
{
// Inside the constructor: store the passed object in the data
// member
this.socket = socket;
}
public void run()
{
try
{
// Input and output streams, obtained from the member socket
// object
outToClient = new DataOutputStream(new
BufferedOutputStream(socket.getOutputStream()));
datain = new ObjectInputStream(new
BufferedInputStream(socket.getInputStream()));
//dataout = new ObjectOutputStream(new
BufferedOutputStream(socket.getOutputStream()));
}
catch (IOException e)
{
return;
}
String name="";
Coordinates location;
Coordinates Destination;
int numberofPassenger;
double chargingPerKilometer;
int carCapacity,did;
Regulations regulations;
boolean connectionActive = true;
String reply="";
while (connectionActive)
{
try
{
if(datain.readObject().getClass()==CarDriver.class)
{
String url
="jdbc:sqlserver://localhost:1433"+";databaseName=EECE350Project;Integrated
Security=True";
String userName = "Mahdi";
String password = "admin";
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn =
DriverManager.getConnection(url,userName,password);
Statement stmt = conn.createStatement();
CarDriver CarDriver1 = (CarDriver)datain.readObject();
name=CarDriver1.getName();
location=CarDriver1.getLocation();
Destination=CarDriver1.getDestination();
numberofPassenger=CarDriver1.getNumofPassengers();
chargingPerKilometer=CarDriver1.getChargingPerKilometer();
carCapacity = CarDriver1.getCarCapacity();
regulations = CarDriver1.getRegulations();
did=CarDriver1.getDid();
reply = "I recieved your connection"+name;
outToClient.write(reply.getBytes(),0,reply.length());
outToClient.write("\\n".getBytes(),0,1);
outToClient.flush();
try
{
System.out.println("Closing Socket");
datain.close();
outToClient.close();
socket.close();
}
catch(IOException ioe)
{
System.out.println("Unable to Close Socket");
}
//String query = "Insert Into EECE 350Project
values(name='"+name+"',did="+did+",XLocation="+location.coordinateX+")";
}
else
{
System.out.println("Hey");
Regulations Pedregulations;
int pid=0;
Coordinates Pedlocation;
Coordinates PedDestination;
Pedestrian Pedestrian1 = (Pedestrian)
datain.readObject();
pid = Pedestrian1.pid;
Pedlocation = Pedestrian1.currentLocation;
PedDestination = Pedestrian1.Destination;
reply= "I recieved your connection";
System.out.println(pid);
outToClient.write(reply.getBytes(),0,reply.length());
outToClient.write("\\n".getBytes(),0,1);
outToClient.flush();
//outToClient.writeBytes(reply);
try
{
System.out.println("Closing Socket");
datain.close();
outToClient.close();
socket.close();
}
catch(IOException ioe)
{
System.out.println("Unable to Close Socket");
}
}
}
catch (IOException ex)
{
Logger.getLogger(SkillsServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (ClassNotFoundException ex)
{
Logger.getLogger(SkillsServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (SQLException ex)
{
Logger.getLogger(SkillsServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
try
{
System.out.println("closing socket");
datain.close();
dataout.close();
socket.close();
}
catch (IOException e)
{
System.out.print('.');
}
}
}
}
The client code : Pedestrian for example
package eece350;
import java.io.Serializable;
import java.io.*;
import java.net.*;
/**
*
* #author user
*/
public class Pedestrian implements Serializable
{
public int pid=0;
public Coordinates currentLocation;
public Coordinates Destination;
public Regulations preferences;
public Pedestrian(Coordinates currentLocation,Coordinates Destination,int
pid,Regulations preferences)
{
this.pid=pid;
this.Destination=Destination;
this.currentLocation=currentLocation;
this.preferences=preferences;
}
public static void main(String argv[]) throws Exception
{
Socket clientSocket = new Socket("localhost", 7171);
ObjectOutputStream outToServer = new
ObjectOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
//ObjectInputStream inFromServer = new
ObjectInputStream(clientSocket.getInputStream());
int pid =0;
double XLocation = 2;
double YLocation = 2;
double XDestination = 4;
double YDestination = 4;
String modifiedSentence = "";
Coordinates currentLocation = new Coordinates(XLocation,YLocation);
Coordinates Destination = new Coordinates(XDestination,YDestination);
Regulations regulations = new Regulations("yes","No","yes","No");
Pedestrian pedestrian1 = new
Pedestrian(currentLocation,Destination,pid,regulations);
outToServer.writeObject(pedestrian1);
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
outToServer.close();
inFromServer.close();
outToServer.flush();
clientSocket.close();
}
}
Please someone help me :(
Effectively you are calling readObject() twice (but there is only one object on the stream).
The problem starts here:
if(datain.readObject().getClass()==CarDriver.class)
With this call, you are consuming the object, but not using it. Then you call readObject() again, which expects another object (but none exists).
Replace with:
Object object = datain.readObject(); // Read it once
if(object.getClass()==CarDriver.class) {
CarDriver carDriver1 = (CarDriver)object;
// process carDriver1;
}
else {
Pedestrian pedestrian1 = (Pedestrian)object;
// process pedestrian1
}
Have you tried:
Object object = datain.readObject();
if (object instanceof CarDriver) {
CarDriver carDriver1 = (CarDriver)object;
// process carDriver1;
}
else if (object instanceof Pedestrian) {
Pedestrian pedestrian1 = (Pedestrian)object;
// process pedestrian1
}
EDIT:
Replace this:
Pedestrian Pedestrian1 = (Pedestrian)datain.readObject();
With:
Pedestrian Pedestrian1 = (Pedestrian)object;
I'm trying to build a server with Java.
My question is: how to do if I have multiple users at the same time? The answer is: multi threading. But I don't know how to do.
For example, if there is two client connected at the same time, and a server (who does 2*number) : if the client1 say "50" to the server and the client 2 "10", the server is supposed to return "100" to the first client and "20" to the second. But i'm not sure my code works.
Server side:
public class Server {
public static void main(String[] args){
ServerSocket socket;
try {
socket = new ServerSocket(4444);
Thread t = new Thread(new Accept(socket));
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
class Accept implements Runnable {
private ServerSocket socketserver;
private Socket socket;
private int nbrclient = 1;
public Accept(ServerSocket s){
socketserver = s;
}
public void run() {
try {
socket = socketserver.accept();
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
String message = in.readLine();
System.out.println(message);
out = new PrintWriter(socket.getOutputStream());
out.println("Pong");
out.flush();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client side:
public class Client {
public static void main(String[] zero) {
Socket socket;
BufferedReader in;
PrintWriter out;
try {
socket = new Socket(InetAddress.getLocalHost(),4444);
out = new PrintWriter(socket.getOutputStream());
out.println("Ping");
out.flush();
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
String message = in.readLine();
System.out.println(message);
socket.close();
}catch (UnknownHostException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
If you have any ideas (how to do multi-threading and how to verify if my code works, like run two Clients.java and check if the multi-threading works)
The Server sides needs a while loop:
public class Server {
public static void main(String[] args){
ServerSocket socket;
try {
while(true){
socket = new ServerSocket(4444);
Socket socketInstance = socket.accept();
Thread t = new Thread(new Accept(socketInstance));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class Accept implements Runnable {
private Socket socket;
private int nbrclient = 1;
public Accept(Socket s){
socket = s;
}
public void run() {
try {
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
String message = in.readLine();
System.out.println(message);//this message should be your number
Double number = Double.parseString(message);
out = new PrintWriter(socket.getOutputStream());
//out.println("Pong");
out.println(2*number +"");
out.flush();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The client side looks ok. Just replace out.println("Ping"); with out.println("50"); or whatever you want.
You first start the server and then you can start multiple client applications. If you have any errors you can then post them here and have a look on an exact scenario.
I have a Server project and a Client project. While the Server is running the first connection from client works fine. At the seccond connection the Server fires the "java.net.BindException: Address already in use: JVM_Bind " error. Is there a way to add more connections on the same port?
Server:
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Socket pipe = null;
while(true){
ServerSocket s = new ServerSocket(2345);
pipe = s.accept();
Connection c = new Connection(pipe);
c.start();
}
}
}
public class Connection extends Thread{
private Socket socket = null;
Mensch jim = null;
ObjectInputStream input = null;
ObjectOutputStream output = null;
ServerSocket s = null;
public Connection(Socket s){
socket = s;
}
public void run(){
try {
input = new ObjectInputStream(socket.getInputStream());
output = new ObjectOutputStream(socket.getOutputStream());
jim = (Mensch) input.readObject();
jim.setAge(33);
output.writeObject(jim);
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
And the Client:
public class Main {
public static void main(String[] args) {
Mensch jim = new Mensch(19, "Jim");
System.out.println(jim.getAge());
try {
Socket s = new Socket("127.0.0.1", 2345);
ObjectOutputStream clientOutputStream = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream clientInputStream = new ObjectInputStream(s.getInputStream());
clientOutputStream.writeObject(jim);
jim = (Mensch) clientInputStream.readObject();
System.out.println(jim.getAge());
clientOutputStream.close();
clientInputStream.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the problem:
while(true) {
ServerSocket s = new ServerSocket(2345);
pipe = s.accept();
...
}
You're trying to bind to the same port repeatedly. All you need to do is create a single ServerSocket and call accept on it multiple times. (I'd also move the pipe variable declaration inside the loop...)
ServerSocket s = new ServerSocket(2345);
while(true) {
Socket pipe = s.accept();
...
}
I am new to java client server communications and I'm confronted with sending an object from client side to server side. Somehow my programm stucks while trying to transfer an object. The likely reason might be the ObjectOutputStream implementation.
Database login button
class Handler implements ActionListener {
Client client = new Client();
List<String> parameterList = new ArrayList<String>();
ClientParameter parameter;
public void actionPerformed(ActionEvent event) {
if(event.getSource()==buttonConnect) {
parameterList.add(username);
parameterList.add(password);
parameter = new ClientParameter(parameterList);
client.connectToServer(parameter);
}
Object ClientParameter
public class ClientParameter {
List<String> parameterList;
public ClientParameter(List<String> parameterList) {
this.parameterList = parameterList;
}
public List<String> getParameterList() {
return parameterList;
}
public void setParameterList(List<String> parameterList) {
this.parameterList = parameterList;
}
}
Class client
public void connectToServer(ClientParameter parameter) {
// Verbindung mit dem Server herstellen
Socket server = null;
try {
server = new Socket("localhost", 3141);
// programm hangs while reading this 2 lines..
ObjectInputStream objectIn = new ObjectInputStream(server.getInputStream());
ObjectOutputStream objectOut = new ObjectOutputStream(server.getOutputStream());
objectOut.writeObject(parameter);
} catch(UnknownHostException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch(IOException e) {
System.out.println(e);
}
}
}
}
And the server class
public class Server {
private static void handleConnection(Socket client) throws IOException {
ObjectInputStream objectIn = new ObjectInputStream(client.getInputStream());
ObjectOutputStream objectOut = new ObjectOutputStream(client.getOutputStream());
ClientParameter parameter;
try {
parameter = (ClientParameter) objectIn.readObject();
System.out.println(parameter);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(3141);
while(true) {
Socket client = null;
try {
client = server.accept();
handleConnection(client);
}
catch(IOException e) {
e.printStackTrace();
}
finally {
if(client!=null) {
try {
client.close();
}
catch(IOException e) {
System.out.println(e);
}
}
}
}
}
}
Thank you!
The server starts by reading what the client sends. And the client also starts by reading what the server sends. So it's a deadlock.
Indeed, as documented, the constructor of ObjectInputStream blocks until it has received the serialization stream header:
A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
Remove the following line, since you don't do anything with the ObjectInputStream anyway:
ObjectInputStream objectIn = new ObjectInputStream(server.getInputStream());