Some background:
I'm part of a team that's developing an Android game for a college course.
I am the person in charge of networking, and my aim is to have a game running in "client mode" submit input to a game running in "host mode". The host will then do all physics/collisions etc, and send back the updated state of the game.
I'm confident that I can compress the state of the game enough that sending the whole state of it will work fine (graphics will be done client-side).
I'm aiming have this game work on a wireless LAN, using IPv4 addresses that I get from
NetworkInterface.getNetworkInterfaces().
All activity code and user input is handled outside of my code, so I'm basically working with Java sockets.
Question:
My code below should send a single packet of a single data byte to the host, telling it that there's client who wants to connect. However, I've used Wireshark to trace all packet activity for about 80 seconds after I run this code, and all I can see is
11 2.825742000 MurataMa_41:d5:ed Broadcast ARP 42 Who has 192.168.0.25? Tell 192.168.0.24
That is, an unanswered ARP request. I've tried multiple ports, in case that was the problem, but I'm currently using 5000.
int hostPort = 5000;
hostSocket = new DatagramSocket(hostPort);
byte [] buffer = new byte[1];
buffer[0] = 'h';
DatagramPacket hello = new DatagramPacket(buffer, buffer.length, hostAddress, hostPort);
hostSocket.send(hello);
So, how can I get the host Android device to respond to ARP requests? I have an Android 2.2 phone sending the requests, and a Nexus 7 running Android 4.2.2, which should be receiving them.
EDIT
I've checked LogCat output for any/all exceptions when sending. There are none.
Related
Problem
I'm developing a remote app to control software on remote machine through sockets.
Between my app and the softwares there is a sort of router/reverse proxy (software) to pass my commands to the desired software.
Unfortunately, for now, this router doesn't support chunked requests, ie all the command must be received in the same TCP packet else it interprets it as two separates ones.
On some devices all goes well. But some others the command is separated in two separates packets and doesn't be interpreted correctly by the router.
I want to prevent request chunking. Is this possible (Android side)?
Technical details
Java code
In my app I'm using a Socket and a DataOutputStream to send commands, like this:
socket = new Socket(ip, port);
out = new DataOutputStream(socket.getOutputStream());
The protocole to communicate with the router is a little bit weird but I need to send an HTTP header first (for a sort of authentication) waiting for an OK from server and then send my commands (without header this time)
I'm doing this like this:
# Sending header
out.writeBytes("SOURCE content HTTP/1.0\n" +
"Content-type: type\n" +
"Authorization: Basic\n" +
"Nom: rouge\n\n");
# Getting server answer
String answer;
int charsRead;
char[] buffer = new char[256];
charsRead = in.read(buffer);
answer = new String(buffer).substring(0, charsRead);
# ... A little bit of computation of the answer to know if it's OK
# Sending my command to server
out.writeBytes("0 rouge violet getNext 1");
# Same as above to get and compute response
Devices used to test
"Chunking" device : LG Nexus 5X - Android 7.1.2 - API 25
"Non chunking" device : Kesa TM708 ($60 cheap tablet) - Android 5.1.1 - API 22
It's exactly the same code on this two devices
Wireshark captures
Here the two requests sent:
Here the chunked capture file (pcap)
Here the not chunked capture file (pcap)
Thank you :)
Ok, I am quite new to network programming and I am trying to solve this problem:
I have GUI based Java SE game for max 7 players and I want it to support multiplayer over the Internet.
Every instance of game would have its own client sending and receiving string.
And here comes the problem I cannot sufficiently solve. I need server and its only functionality is keeping client's sockets opened and on receiving some string just forward it to other clients. My first idea was to run server on the first player's machine and other players can connect to that server via its IP from outside. Now I discovered that getting public interface IP is not that easy as I thought so I searched and found the code written below to get some IP's that SHOULD be available from outside. When I try this at localhost, resulted IP is always some IPv6 + port and connecting from client using this credentials is successful and it works. When I start the server on another machine and copy these credentials for connecting from another computer it fails (it either doesn't connect or if it does and client sends message, server doesn't receive any).
So my next idea was to use some public IP on remote hosting server. So there would be some server running 24/7 (or if I programmatically from game tell him so) and I use its IP to unite all clients. I just don't know how to make this thing working and what technologies use.
I hope I explained my problem clearly and thanks for any ideas or even solutions :)
Get machine's public interface IP (where server is running) and prints that out code:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface iface = interfaces.nextElement();
if (iface.isLoopback() || !iface.isUp()) { //127.xxx loopback
continue;
}
Enumeration<InetAddress> addresses = iface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
String tmp = addr.getHostAddress();
if (tmp.startsWith("192.168.") //local IP
|| tmp.startsWith("10.") //local IP
|| tmp.startsWith("172.16.") //local IP
|| tmp.startsWith("172.31.") //local IP
|| tmp.startsWith("169.254") //single network IP
|| tmp.equals("255.255.255.255")) { //broadcast address
continue;
}
//cut "%net9","%wlan" etc stuff off
IP = tmp.substring(0, Math.max(0, tmp.indexOf('%')));
port=server.getPort();
System.out.println(IP + " " + port);
}
}
if running on a "local network" then having a serversocket is fine, but we deal with NAT and the internet which means that 98% of machines are not directly internet visible. (i.e. opening a TCP port for listening on the machine will not result in the machines Internet IP address having that port be listened to. )
The initial option would be to have a server on public hosting which mediates communication between players and each players machine is responsible for maintaining 'game state' but then you run into the issue of synchronization. (e.g. one players machine thinks that they have hit and killed another player prior to that machine receiving a command to tell it that the opponent has moved. )
The current method of thinking for this paticular problem is to have the server maintain the 'game state' (e.g. player positions, health, weapon damage, etc. )
having players send 'commands' to the server (e.g. move, fire, jump. ) and then having the server report to all players the 'minor' game state changes. (so Time becomes an important factor and all messages between clients and server need to be timestamped. )
so your clients maintain what they believe 'game state' to be, recieving updates from the server to 'correct' errors.
In addition to this every once in a while the server should send a dump of the entire 'game state' to each player as a 'sync' message to ensure what they believe to be the game state 'is' the actual game state.
If your language of choice was "C" it would be trivial to take the md5 checksum of the entire game state structure and then transmit this to players periodically and only performing a sync message..
The links below should give you a good starting point.
A good start
And the enclosing page with a little bit more detail
I'm implementing a FTP program using UDP in Java (TCP is not an option), but I'm having trouble grasping the basics of how it's supposed to work.
As I understand, it's connectionless, so I should just have one server thread running which processes every request by any client.
Where I'm getting confused is during the actual file transfer. If the server is in the middle of a loop sending datagrams containing bits of a requested file to the client, and is waiting for an ACK from the client, but instead of that receives a completely different request from a different client, how am I supposed to handle that?
I know I could jump out of the loop to handle it, but then if the initial expected packet finally arrives, how can I pick up where I left off?
A UDP server works similar to a TCP in many respects. The major difference is that you will not receive a acknowledgement that your packets were received. You still have to know which client you are sending to, so use the DatagramSocket class. This is the Oracle tutorial for UDP: http://docs.oracle.com/javase/tutorial/networking/datagrams/index.html. It has a pretty good example in it. The significant part is getting the address and port of the original client, and returning your packets to that client:
InetAddress address = packet.getAddress();
int port = packet.getPort();
new DatagramPacket(buf, buf.length, address, port);
You could start a new thread on the server side for sending the bits every time a client sends a request. The thread would save the return address and port of the client, and die when the file send was done.
My Android device+app is continuously sending data every few ms, and I'd like to receive it on my web browser application that I'm building with JavaScript/HTML.
In the Android/Java app I do the following over socket:
//Initialize, where PORT = local ip of my laptop with web server I guess.
//and I choose an available port on my network, say 8080.
echoSocket = new Socket(HOST, PORT);
out = new PrintWriter(echoSocket.getOutputStream(), true);
//Sending data every few ms:
JSONObject j = new JSONObject();
j.put("x", params[0]);
j.put("y", params[1]);
j.put("z", params[2]);
String jString = j.toString();
out.println(jString);
So I have something like {"x": 1.0023532, "y": 2.454234, "z": 6.234583}.
In other Java applications, I've done this communication by having my receiver application create a ServerSocket on the particular PORT used above. Then as long as I have the right local IP address for my laptop, I can do serverSocket = new ServerSocket(PORT); etc.
Now, how can I accept this data in a web application (JavaScript/HTML)? I've heard of websockets but have no idea how to initialize and use for this purpose - hopefully it's pretty straightforward.
I dont think its possible to send data directly to the browser without a middle man (server). If you want to create a fast and easy server to ping data back and forth I would have some fun with NodeJs. I havent gotten a chance to ever use the stuff but I did have some fun playing with it. It could be something to look into expecially if your just pinging data back and forth between clients.
I watched this video "Introduction to Node.js with Ryan Dahl" a while ago and he showed a basic example that does pretty much what your talking about. Just a thought, plus it would be a fun and fast implementation.
On a side note I do believe Amazon AWS has a instance for Node JS if you want to bring it to a live server. Im pretty sure you can setup a micro instance for no cost.
I'm trying to make a port of a chat program a friend of mine made with lacewing and multimedia fusion 2 for android device.
I've managed to create a socket connecting to the listening socket of the server successfully, but I cannot seem to be able to send data to login and enter the chat. The login for now just requires a name, but even if I send a String of data, the server doesn't seem to reply or accept that data to get me over the channel.
I know I could easily port this with other way like using the NDK of the multimedia fusion 2 exporter, but I just want to figure out how this works
PS: I'm using Java and libgdx for the development
You need to read the liblacewing relay protocol:
https://github.com/udp/lacewing/blob/0.2.x/relay/current_spec.txt
On initial connection, you have to send byte 0 to identify that you are not an HTTP client. After this, you can exchange normal protocol messages.
The first message you need to send is the connection request (which may be denied by the server with a deny message). This would be:
byte 0 (2.1.0 request)
(1.2 size)
byte 0 (2.1.0.0 connection request)
string "revision 3" (2.1.0.0 connection request -> version)
When the server responds with response 0 (2.2.0.0 Connect), you then have to set a name before you may join any channels. This is done with message 2.1.0.1 SetName, which is the same structure as above but instead of 2.1.0.0's byte 0, it is 2.1.0.1's byte 1, followed by the name as a string instead of the protocol version.
The server should then respond with 2.2.0.1 SetName, assuming it accepted your name change request. You should process this message in case the server gave you a different name than you requested. Finally, once you have a name, you can join a channel with 2.1.0.2 JoinChannel. The flags you specify here will be used if the channel doesn't exist yet (e.g. nobody is in the chat yet) - these should match the ones in the MMF2 project file. The name should also match.
After all that, you're still not done! You have to process more messages, etc. it's almost like writing the RelayClient class yourself. It's a tough task, but with the protocol specification in hand you should be able to work it all out.