Jump to content
Jumbofile

Java UDP questions

Recommended Posts

Im creating a game using Godot as a client and Java as a server. My main question is how does the server and client differentiate between packets. Like how does the server know that the packet I just sent is the players coordinates. Any explanation will help and java code examples would be even better.

Share this post


Link to post
Share on other sites

Typically the server has a some sort of connection identification, whether or not it is implemented at the network layer or in the library you are using, or whether you have to implement it yourself is not something I can answer, as I am not familiar with the technology you mentioned you are using for the client, and it can vary a lot.

Essentially in its barest form the client is sending some sort of connection identifier in each packet to the server. Same principle applies to coordinates. Just like there is an identifier for who is connecting (which should be two part -- when the client is initially connecting it should pass some sort of key to the server to say "hey this is me, please give me access", and the server will generate another key to use in tandem with the key the client provided for subsequent requests to prove to both the client and server that "hey, this packet was sent by someone claiming to be X client, and X client should know about Y piece of information, which they do, so they must really be X client"), there is also an identifier for what kind of information is being sent to the server -- unlike the connection identifier however which is dynamic and only known at runtime, this is static, and is known to all clients and servers beforehand.


Before you jump the gun and implement connection identifiers however, check to see if you get multiple sockets or connections from your server networking library. If you only get a single one that spits out packets, you will need to write your own connection identification code -- which means all of your packets will have a client identifier generated by the client, a shared secret between the client and server that the server generated on the connection request, the packet type/identifier, and finally the packet data, but if the server library provides connection and socket information for each socket/connection, this is likely already being taken care of, and all you need are the packet identifier/type and packet data.

Share this post


Link to post
Share on other sites

So currently the server, which uses java's standard networking library, automatically takes the port and IP of the client and uses that to send the information back. I guess thats the connection identifier. My main problem is that im sending the server a string that contains the x and y cords of the player (ex : 500,300). From there how would you take that information and define what it is used for? 

Share this post


Link to post
Share on other sites

In each packet the first set of information (before the coordinates) would be an identifier of what kind of packet it is. 

 

For example:

Packet 1 would be login

Packet 2 would be movement

Packet 3 would be logout. 

 

So if you got a packet with the following values (2, 500, 300) you'd know that you should process the data as a movement packet and the coords would be 500,300. 

 

Then all you need to do is match the connection where you received that info to a player/client and set their position to those coords. 

 

Edit: There are other methods for handling this but for learning and getting started purposes simple integer identifiers will be fine. 

Share this post


Link to post
Share on other sites

So using all of yalls information and some stuff I found online I basically came up with this solution:

The client sends a "message key" ex: PLAYER_MOVE and the server accepts that key. After the key the client sends the actual packets used to transfer the data that is needed. The server then takes the key and compares it a switch statement and if it matches (which it should) it will do something specified in that case with the other packet(s).

 

Is this the way I should be doing this?

Share this post


Link to post
Share on other sites
1 hour ago, Jumbofile said:

So using all of yalls information and some stuff I found online I basically came up with this solution:

The client sends a "message key" ex: PLAYER_MOVE and the server accepts that key. After the key the client sends the actual packets used to transfer the data that is needed. The server then takes the key and compares it a switch statement and if it matches (which it should) it will do something specified in that case with the other packet(s).

 

Is this the way I should be doing this?

 

 

That is basically how its done. The only thing I would say is that you should send it all in 1 packet. Simplifies things if a packet gets lost or takes longer or arrives out of order. This is not as big of an issue as it used to be, but UDP does not guarantee order like TCP. Also its just more effective to send 1 packet.

 

I dont know what language you use, but normally I create a enum (number) like JC said. So my code looks a bit like this.

 

int PLAYER_MOVE = 1;

int PLAYER_CONNECT = 2;

 

PlayerMoveData

{
 int x;

 int y;

}

 

ConnectData

{
 

}

 

Packet

{
    type = PLAYER_MOVE;

    PlayerMoveData data;

}

 

 

So when I get the packet, I read the first value and then decide what to do with the rest of the information based on what type of packet it is. I am not sure this will translate to the language your using. But if you can try to only read the first bit of the packet to find out the type, then do something with the rest.I do not know java so I cant say how to do it. But here is some mockup code in a c++ ish language. The hardest part of the above is probably reading a partial packet before you know the rest of the information. It is fairly trivial in c++ if that's what you are using.

 

If you have a packet like:

 

void* packetData;

 

you could do:

 

const int* identifier = packetData;

if(*identifier == PLAYER_MOVE)

{

    PlayerMoveData* moveData= static_cast<char*>(packetData) + sizeof(int);

   

}

Share this post


Link to post
Share on other sites
3 minutes ago, Mighty Professional said:

You are only sending 1 object. However, that object contains 2 objects. The identifier and the real object. Does godot support that? 

 

Also have you read: http://docs.godotengine.org/en/3.0/tutorials/networking/high_level_multiplayer.html ?

 My server isnt in godot so I didnt use their high-level networking library. Im using a custom java server.

Share this post


Link to post
Share on other sites

When it comes directly to godot I don't know anyone who has used it so im not sure how much help we will be. 

 

Does godot have a forum community? They might be able to fill in the remaining blanks better than we can. 

Share this post


Link to post
Share on other sites

Ill try their forums, doesnt seem as friendly and they assume you know more.

So how im doing it on the godot end:

First I make the string

var x = pos.x

Then I have to convert it to byte[]

var xS = x.to_ascii()

Finally I send it to the server (they only let me put one argument in this method)

socketUDP.put_packet(xS)

I appreciate the help so far, it has allowed me to move my character using a server. 

Share this post


Link to post
Share on other sites

Could you make a list or array in godot and pass that to put_packet?

 

It looks like you could do this:

var pos = "2,500,400"

var packet = pos.to_ascii()

socketUDP.put_packet(packet)

 

Then on the other side you'd have to split that string by commas to get your three values.

Share this post


Link to post
Share on other sites
class Packet {

    List<Object> _packetData;

    private Packet(string identifier) {
        _packetData.add(identifier);
    }

    private Packet(string identifier, object[] data) {
       _packetData.add(identifier);
       _packetData.add(data);
    }

    void put(object data) {
         _packetData.add(data);
    }
    
    public static Packet StreamToPacket(object[] data) {
        return new Packet(dataStream[0].ToString(), data);
    }  

    public static Packet Create(string identifier) {
        return new Packet(identifier);
    }

}

var movingPacket = new Packet("moving");
movingPacket.put(100);
socketUDP.put_packet(movingPacket);

 

There's some conceptual pseudo-code I whipped up really quickly at work. Not sure of the specifics of what you need to do, but the general principle should apply. If you can only send one object at a time, make that object one which contains all of the needed data for that packet. In other words, treat each packet as an object.

Share this post


Link to post
Share on other sites

I'm with JC. I don't know how godot language works, but sending data as a string should work without any problem. Only with that you should manage all info the client and the server have to manage. I would start doing that while I don't find any better way and then, if I find one, I would optimize the code(even when doing this could mean tons of work). At least you'll have a pre-alfa version to work with.

Share this post


Link to post
Share on other sites

Ok so this is how I do it now

 

This is the client:

func send_player_cord(var x, var y):
	#tell the server what you are trying to do
	var content = "PLAYER_POS," +  str(x) + "," + str(x)
	var yS = content.to_ascii()
	socketUDP.put_packet(yS)

 

This is the server:

// Receive a packet
			DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
			socket.receive(packet);
			
			//recieve messageID to decide what to do with the packet
			String packetData = new String(packet.getData(), packet.getOffset(), packet.getLength());
			//Grab message
			String messageID = packetData.substring(0, packetData.indexOf(','));
			//Get senders ipaddress
			InetAddress IPAddress = packet.getAddress();
			
			//Get senders port
			int port = packet.getPort();
			System.out.println(messageID);
			//Do stuff based on messageID
			switch(messageID){
				case "PLAYER_POS":
					//set packets to string
					String pX = packetData.substring(packetData.indexOf(',') + 1, packetData.lastIndexOf(','));
					String pY = packetData.substring(packetData.lastIndexOf(',') + 1);
					//ystem.out.println(pX + ", " + pY);
					
					//Set player initial position
					serverPlayer.setPlayer(pX, pY);
					break;

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×