Java: XML object - java

I'm making simple peer to peer game and I decided to use XML to send information over sockets(example below). But I'm not sure how to send it ? I should simply use ObjectOutputStream.writeObject(obj) and as parameter use object from my example ?
Mainly I'm asking, how does look proper sending XML objects over sockets.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class SendIPObject {
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(IPSender.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Player object = new Player();
object.setID(0);
object.setIP("192.167.211.167");
m.marshal(object, System.out);
}
}
import java.io.Serializable;
abstract public class Player implements Serializable{
private String ip;
private int id;
public String getIP() {
return ip;
}
public int getID() {
return id;
}
public void setIP(String ip) {
this.ip = ip;
}
public void setID(int id) {
this.id = id;
}
}

XML is sent as plain string. So first step would be to create clients that can send and receive from each other strings, e.g. "Hello, world.". Next you need to create an object and using JAXB convert to String and send. Than receive it on other client and using JAXB again. This way you can easily debug what you send and receive. Once you've done it you can try to avoid converting to temporary xml string and use socket streams directly on marshalling and unmarshalling.
I think you shouldn't use ObjectOutputStream because it serializes object to byte array. But you need to "serialize" your object to XML (string) and send it.
Here you can see how can you marshal object to java String: I want to convert an output stream into String object

If the sender and receiver are both java based, you can actually skip the converting to xml back and forth, and send the object over ObjectInputStream. This is essentially an alternative to using xml. You could also use the ObjectInputStream with the String class if you wanted to.
I changed your Player class slightly to to be concrete and have added a toString() method to show what was received on both ends.
Here is how the client looks:
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Player player = new Player("192.168.1.10", 1);
//create connection
Socket sock = new Socket("127.0.0.1", 8080);
//get teh output stream to send in over
ObjectOutputStream cout = new ObjectOutputStream(sock.getOutputStream());
//send it
System.out.println("Sending: "+player.toString());
cout.writeObject(player);
//close connection
sock.close();
System.out.println("Closed");
}
}
Here is how the Server looks:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
try {
System.out.print("\nserver>> ");
// listen for connection from client
Socket sock = serverSocket.accept();
System.out.println("CONNECTION ACCEPTED");
ObjectInputStream sin = new ObjectInputStream(sock.getInputStream());
//read the player in
Player player = (Player) sin.readObject();
System.out.println("from Client>> " + player.toString());
// close the connection
sock.close();
System.out.println("server>> CONNECTION CLOSED");
System.exit(0);
} catch (Exception e) {
}
}
}
}

Related

json file not arriving complete when using sockets

I have a stream of video. And every frame I need to send a small json file with data from that frame, speed it´s crucial. Whats the best way to do this?
My Server is something like this. Waits for a json file and then has to send that json file to a python application.
public class ServerClass {
public static void main(String[] args) {
Marcoserver mimarco=new Marcoserver();
}
}
class Marcoserver implements Runnable {
public Marcoserver(){
Thread miHilo = new Thread(this);
miHilo.start();
}
public void run() {
try {
ServerSocket server = new ServerSocket(7777);
while (true) {
Socket miSocket = server.accept();
BufferedReader entrada = new BufferedReader(new InputStreamReader(miSocket.getInputStream(), "UTF8"));
String mensaje = entrada.readLine();
JSONObject obj;
obj = new JSONObject(mensaje);
System.out.println(obj);
ConectorSocket cntor = new ConectorSocket("localhost", 6363);
cntor.Conectar();
cntor.Send(mensaje);
cntor.Close();
miSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ConectorSocket{
private String host;
private int port;
Socket sockSend;
public ConnectClass(String hst, int prt ) {
this.host = hst;
this.port = prt;
}
public void Conectar() {
this.sockSend = new Socket(this.host, this.port);
}
public void Send(String mensaje) {
DataOutputStream flujo_salida = new DataOutputStream(sockSend.getOutputStream());
flujo_salida.writeBytes(mensaje);
flujo_salida.close();
}
public boolean Close() {
this.sockSend.close();
}
}
This is the python app simplified:
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 6666))
serversocket.listen()
while True:
connection, address = serversocket.accept()
buf = connection.recv(2048)
if len(buf) > 0:
print(buf.decode())
My problem is that the python app prints incomplete information such as:
{"keyword"
{"keyword": [[14, 1, -1]]}
{"keyword": [[14,
instead of:
{"keyword":[]}
{"keyword":[[14,1,-1]]}
{"keyword":[[14,2,-1]]}
There's nothing wrong with your Java code, but your Python code is not good:
while True:
connection, address = serversocket.accept()
buf = connection.recv(2048)
if len(buf) > 0:
print(buf.decode())
That will print just the first received TCP packet for each connection.
You need to continue calling recv until it returns 0:
while True:
connection, address = serversocket.accept()
msg = []
while True:
buf = connection.recv(65536)
if (len(buf) == 0):
break
msg.append(buf)
print(''.join(msg))
connection.close()
You also need to close each connection.

How to connect two different PCs between two different networks using a java chat application?

I have a chat application client server which run on a LAN without a server.
this is the server class:
import java.net.*;
import java.io.*;
public class Server {
private ServerSocket server;
private Socket connessione;
private BufferedReader dalClient;
private PrintStream alClient;
private String name;
public Server(String name) {
this.name = name;
try {
InetAddress IP=InetAddress.getLocalHost();
System.out.println("IP of my system is := "+IP.getHostAddress());
server = new ServerSocket(1000, 5);
System.out.println("Server attivo");
connessione = server.accept();
dalClient = new BufferedReader(new InputStreamReader(connessione.getInputStream()));
alClient = new PrintStream(connessione.getOutputStream());
}
catch(IOException e) {
System.out.println(e);
}
} // Server()
public void conversazione() {
String messaggio = "";
BufferedReader t = new BufferedReader(new InputStreamReader(System.in));
try {
alClient.println("Sei connesso al server! Digita /logout per effetuare la disconnessione.\n");
while(!messaggio.equals("/logout")) {
messaggio = dalClient.readLine();
System.out.println(messaggio);
if(!messaggio.equals("/logout")) {
messaggio = t.readLine();
alClient.println(name+" scrive: "+ messaggio);
}
} // while
}
catch(IOException e) {
System.err.println("Conversazione interrotta");
}
}
}
and this is the client class:
import java.net.*;
import java.io.*;
public class Client {
private Socket connessione;
private BufferedReader dalServer;
private PrintStream alServer;
private String name;
public Client(String name) {
this.name = name;
BufferedReader t = new BufferedReader(new InputStreamReader(System.in));
try {
int porta = getLocalPort();
System.out.println("Porta locale: " + porta);
System.out.println("Inserire indirizzo IP server: ");
String indirizzo = t.readLine();
connessione = new Socket(indirizzo, 1000);
dalServer = new BufferedReader(new InputStreamReader(connessione.getInputStream()));
alServer = new PrintStream(connessione.getOutputStream());
} catch(IOException e) {
System.out.println(e);
}
} // Client()
public void conversazione() {
String messaggio = "";
BufferedReader t = new BufferedReader(new InputStreamReader(System.in));
try {
while(!messaggio.equals("/logout")) {
messaggio = dalServer.readLine();
System.out.println(messaggio);
if(!messaggio.equals("/logout")) {
messaggio = t.readLine();
alServer.println(name+" scrive: "+messaggio);
}
} // while
connessione.close();
}
catch(IOException e) {
System.out.println("Conversazione interrotta");
}
} // conversazione()
}
and i have other two class files which i use to run the codes above that are the follow:
this is the class which i execute to run the server side:
public class ProvaServer {
public static void main(String[] args) {
Server s = new Server(args[0]);
s.conversazione();
}
}
this is the class which i execute to run the client side:
public class ProvaClient {
public static void main(String[] args) {
Client c = new Client(args[0]);
c.conversazione();
}
}
The code works well if i open two prompt (on the same pc connected in the same network) and do that:
- in one prompt i run server class
- in the other prompt i run the client class
After running client class i insert my localhost and it work well.
The code works well also if i open a prompt on a pc and the other prompt on another pc (but connected in the same network)
- in one prompt (1st pc) i run server class
- in the other prompt (2nd pc) i run the client class
After running client class i insert the IP address (IPV4) of the other machine and it work well.
After this explanation, i ask you, how can i modify the code to make the code working beetween two PCs connected TO DIFFERENT NETWORKS whithout using a phisical server?

Java private messaging

i am having a problem with private messages in java. I ask the user for a "name" when they launch the Client, and it is a variable in ChatClient.java file. I have made it "public", but when i try to call it in the ChatServer.java it says "cannot find symbol". Any help with that? Also in this snippet i am searching for the right "name" from users, should there be anything defiying the "i" name? (like i.name or some sort of connection between the current client and their name).
ChatServer problematic part
public void sendPrivate(String message) throws Exception {
Iterator<Socket> i = clients.iterator();
StringTokenizer st = new StringTokenizer(message.substring(7,message.length()),", ");
String realMessage = st.nextToken();
String to = st.nextToken();
while (i.hasNext()) {
Socket socket = (Socket) i.next();
try {
if (name.equals(to)){
DataOutputStream out = new DataOutputStream(socket.getOutputStream()); // create output stream for sending messages to the client
out.writeUTF(realMessage); // send message to the client
}
}
catch (Exception e) {
System.err.println("[system] could not send message to a client");
e.printStackTrace(System.err);
}
}
}
ChatClient part where the user inputs their "name"
public class ChatClient extends Thread
{
public String name;
protected int serverPort = 8888;
public static void main(String[] args) throws Exception {
new ChatClient();
}
public ChatClient() throws Exception {
Socket socket = null;
DataInputStream in = null;
DataOutputStream out = null;
//whitelistaned
String[] whitelist = {"Bob", "Frank", "Goliath", "Zealot", "Bruce Wayne"};
int aliUstrezas = 0;
//common courtesy
System.out.println();
System.out.println("Would you fancy in telling me your name, sir ?");
System.out.println("Current whitelist: {'Bob', 'Frank', 'Goliath', 'Zealot', 'Bruce Wayne'} ");
Scanner sc = new Scanner(System.in);
name = sc.nextLine();
ChatServer does not instantiate a object of type ChatClient, so it does not matter if name is public or not, it can not magically read variables from any arbitrary object.

Java error - Send is not abstract and does not override abstract method run() in Runnable

I am getting the following error when I try to compile my java work.
Send.java:16: error: Send is not abstract and does not override abstract method run() in Runnable
public class Send implements Runnable {
^
1 error
My code for Send.java is
public class Send implements Runnable {
private byte[] data = new byte[0];
private String from = "";
static DataOutputStream out = null;
public Send(byte[] data, String from) throws IOException {
data = data;
from = from;
out = Server.os;
Log.logInfo("Data:" + DatatypeConverter.printHexBinary(data) + "");
Log.logInfo("From:" + from + "");
Log.logInfo("OS:" + out + "");
}
}
And the code for defining the os outputstream in the server file is:
public class Server implements Runnable {
private Socket socket;
public static DataOutputStream os = null;
private DataInputStream is = null;
public Server(String originalHost) throws Exception {
socket = new Socket(originalHost, 9339);
Log.logInfo("* Connected to Server");
}
#Override
public void run() {
int bytes_read;
try {
DataInputStream is = new DataInputStream(socket.getInputStream());
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
....
I need to keep the send.java code for getting the outputstream the same because soon it will also be getting the same variable from another file depending on an if statement.
Does any have an idea on how to fix this?
Thanks!
You have the Send class implement the Runnable interface but do not override the run() method like you do in your server class.
Implement the following method inside of your Send class:
#Override
public void run() {}

Running a Client-Server Chat program

This is one of the most common application scenario that can be found all over the net. and I'm not asking any questions about the java codes that I did because I was successful in running it on my laptop where both the client and server part of the .java file resides. Rather I have had problem getting it to work in between two computers. I tried establishing physical connection using cross-over cable to connect two computers, and did a test to see if file transfers successfully and it did, however, keeping one Server part of the .java file in one computer and client part in the other, I tried to run the server first and then the client but it got a "access denied" error.
For reference here's my two .java files:
/* ChatClient.java */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ChatClient {
private static int port = 5000; /* port to connect to */
private static String host = "localhost"; /* host to connect to (server's IP)*/
private static BufferedReader stdIn;
private static String nick;
/**
* Read in a nickname from stdin and attempt to authenticate with the
* server by sending a NICK command to #out. If the response from #in
* is not equal to "OK" go bacl and read a nickname again
*/
private static String getNick(BufferedReader in,
PrintWriter out) throws IOException {
System.out.print("Enter your nick: ");
String msg = stdIn.readLine();
out.println("NICK " + msg);
String serverResponse = in.readLine();
if ("SERVER: OK".equals(serverResponse)) return msg;
System.out.println(serverResponse);
return getNick(in, out);
}
public static void main (String[] args) throws IOException {
Socket server = null;
try {
server = new Socket(host, port);
} catch (UnknownHostException e) {
System.err.println(e);
System.exit(1);
}
stdIn = new BufferedReader(new InputStreamReader(System.in));
/* obtain an output stream to the server... */
PrintWriter out = new PrintWriter(server.getOutputStream(), true);
/* ... and an input stream */
BufferedReader in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
nick = getNick(in, out);
/* create a thread to asyncronously read messages from the server */
ServerConn sc = new ServerConn(server);
Thread t = new Thread(sc);
t.start();
String msg;
/* loop reading messages from stdin and sending them to the server */
while ((msg = stdIn.readLine()) != null) {
out.println(msg);
}
}
}
class ServerConn implements Runnable {
private BufferedReader in = null;
public ServerConn(Socket server) throws IOException {
/* obtain an input stream from the server */
in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
}
public void run() {
String msg;
try {
/* loop reading messages from the server and show them
* on stdout */
while ((msg = in.readLine()) != null) {
System.out.println(msg);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
and here's the ChatServer.java:
/* ChatServer.java */
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Hashtable;
public class ChatServer {
private static int port = 5000; /* port to listen on */
public static void main (String[] args) throws IOException
{
ServerSocket server = null;
try {
server = new ServerSocket(port); /* start listening on the port */
} catch (IOException e) {
System.err.println("Could not listen on port: " + port);
System.err.println(e);
System.exit(1);
}
Socket client = null;
while(true) {
try {
client = server.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.err.println(e);
System.exit(1);
}
/* start a new thread to handle this client */
Thread t = new Thread(new ClientConn(client));
t.start();
}
}
}
class ChatServerProtocol {
private String nick;
private ClientConn conn;
/* a hash table from user nicks to the corresponding connections */
private static Hashtable<String, ClientConn> nicks =
new Hashtable<String, ClientConn>();
private static final String msg_OK = "OK";
private static final String msg_NICK_IN_USE = "NICK IN USE";
private static final String msg_SPECIFY_NICK = "SPECIFY NICK";
private static final String msg_INVALID = "INVALID COMMAND";
private static final String msg_SEND_FAILED = "FAILED TO SEND";
/**
* Adds a nick to the hash table
* returns false if the nick is already in the table, true otherwise
*/
private static boolean add_nick(String nick, ClientConn c) {
if (nicks.containsKey(nick)) {
return false;
} else {
nicks.put(nick, c);
return true;
}
}
public ChatServerProtocol(ClientConn c) {
nick = null;
conn = c;
}
private void log(String msg) {
System.err.println(msg);
}
public boolean isAuthenticated() {
return ! (nick == null);
}
/**
* Implements the authentication protocol.
* This consists of checking that the message starts with the NICK command
* and that the nick following it is not already in use.
* returns:
* msg_OK if authenticated
* msg_NICK_IN_USE if the specified nick is already in use
* msg_SPECIFY_NICK if the message does not start with the NICK command
*/
private String authenticate(String msg) {
if(msg.startsWith("NICK")) {
String tryNick = msg.substring(5);
if(add_nick(tryNick, this.conn)) {
log("Nick " + tryNick + " joined.");
this.nick = tryNick;
return msg_OK;
} else {
return msg_NICK_IN_USE;
}
} else {
return msg_SPECIFY_NICK;
}
}
/**
* Send a message to another user.
* #recepient contains the recepient's nick
* #msg contains the message to send
* return true if the nick is registered in the hash, false otherwise
*/
private boolean sendMsg(String recipient, String msg) {
if (nicks.containsKey(recipient)) {
ClientConn c = nicks.get(recipient);
c.sendMsg(nick + ": " + msg);
return true;
} else {
return false;
}
}
/**
* Process a message coming from the client
*/
public String process(String msg) {
if (!isAuthenticated())
return authenticate(msg);
String[] msg_parts = msg.split(" ", 3);
String msg_type = msg_parts[0];
if(msg_type.equals("MSG")) {
if(msg_parts.length < 3) return msg_INVALID;
if(sendMsg(msg_parts[1], msg_parts[2])) return msg_OK;
else return msg_SEND_FAILED;
} else {
return msg_INVALID;
}
}
}
class ClientConn implements Runnable {
private Socket client;
private BufferedReader in = null;
private PrintWriter out = null;
ClientConn(Socket client) {
this.client = client;
try {
/* obtain an input stream to this client ... */
in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
/* ... and an output stream to the same client */
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.err.println(e);
return;
}
}
public void run() {
String msg, response;
ChatServerProtocol protocol = new ChatServerProtocol(this);
try {
/* loop reading lines from the client which are processed
* according to our protocol and the resulting response is
* sent back to the client */
while ((msg = in.readLine()) != null) {
response = protocol.process(msg);
out.println("SERVER: " + response);
}
} catch (IOException e) {
System.err.println(e);
}
}
public void sendMsg(String msg) {
out.println(msg);
}
}
Now, what should I do in order to run this two files from two computers given that I have the physical connection(TCP/IP) setup already??
Thanks in advance... :)
Sounds like it's quite possibly a firewall problem. Have you tried opening a hole in your firewall for port 1001?
Have you also looked at your java.policy and make sure that it is configured to allow local codebase to open sockets?
as mentioned in comment, you should not use port < 1025 for you applications, since they are always used in deamon processes. However you should test your program like this
1) if you get connection refused then you should check the exception properly, whether client program takes time before generating exception ( that mean request is going to server and then it's giving connection refused), in that case you should try java.policy put following in a file named java.policy
grant {
permission java.net.SocketPermission ":1024-65535",
"connect,accept";
permission java.net.SocketPermission ":80", "connect";
permission java.io.FilePermission "", "read,write,delete";
permission java.security.SecurityPermission "";
};
while compiling use this flag -Djava.security.policy=java.policy
more-over you should also try -Djava.rmi.server.hostname=IP, where IP is clien-ip for client.java and server-ip for server.java
2) if you are immediately getting exception at client side then your request is not going outside your pc, so client has some problem.
check the exception properly and post them over here.
3) though i've not got access denied error, but it seems to have port problem that might be solved using policy or port>1024.
post what are you getting now.

Categories

Resources