目前我有一台允许客户端通过发送消息“connect”连接到它的服务器,当服务器收到此消息时,它接收InetAddress,然后使用该InetAddress将数据发送到客户端,一旦客户端连接并收到其ID号,它将不断向UDP套接字发送数据,以便更新其位置,现在当新客户端想要连接时,它将发送消息“connect”但很少发送新客户端将连接,正在发生的事情是已连接的客户端正在保持host.receive功能忙,所以当新客户端进行连接时,如果连接的当前客户端没有跳转,那么很幸运,然后客户端只剩下一个空白屏幕。
我需要帮助的是,如何使用相同的端口支持UDP套接字上的多个客户端? 将连接到服务器的所有客户端都在同一个路由器上,
这是整个服务器代码
public class gameServer /*extends Thread*/ extends AsyncTask<String, String, String>{
/**
* Sets up a server for Android applciation
*/
private static final String TAG = "GameServer";
private DatagramSocket socket;
private int port = 50000;
private int players = 0;
private String[] positions = new String[8];
private ArrayList<InetAddress> addresses = new ArrayList();
private boolean wait = false;
private Context contextHolder = null;
//Make an array, this array will hold all the positions
//the clients sent to it,
//using the ID number, it will store it in a array block
//and the "host" can just return it and use that
public gameServer( Context context ) throws IOException
{
//Here we take in the clients block,
//this will be assets[0];
contextHolder = context;
socket = new DatagramSocket( port );
Log.d(TAG, "Server was setup");
}
public DatagramSocket rtnSocket(){ return socket; }
private String getLocalIPAddress()
{
try
{
for (Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); nis.hasMoreElements();)
{
NetworkInterface ni = nis.nextElement();
Log.v(TAG, "NetworkInterface = " + ni.getDisplayName());
for (Enumeration<InetAddress> ips = ni.getInetAddresses(); ips.hasMoreElements();)
{
InetAddress ip = ips.nextElement();
String s = ip.getHostAddress();
Log.v(TAG, "InetAddress = " + s);
if (!ip.isLoopbackAddress())
{
if(InetAddressUtils.isIPv4Address(s)) return s;
}
}
}
}
catch (SocketException e)
{
Log.e(TAG,"getLocalIPAddress()", e);
}
return null;
}
public void getClientPosition(int xPos, int yPos)
{
positions[0] = xPos + ":" + yPos;
}
@Override
protected String doInBackground(String... params) {
InetAddress client = null;
boolean run = true;
String data = "";
DatagramPacket packet = null;
boolean position = false;
while( run )
{
if( data.equalsIgnoreCase( "" ) )
{
}
//Send some data
if( data.equalsIgnoreCase( "connect" ) && wait == true )
{
Log.d(TAG, "Someone wants to connect");
//Increase the total players by 1
players = players + 1;
//Notify to the host (client) something has change
//notify client
//Send a message to the client with the ID
byte[] bufer = new byte[256];
//Send a message "connect" to the host
String msg = Integer.toString( players );
int msgLength = msg.length();
bufer = msg.getBytes();
InetAddress address;
//Default ip address of the host
//Take the address from the packet
addresses.add( packet.getAddress() );
Log.d(TAG, "Address is " + addresses.get( addresses.size() - 1 ) );
address = addresses.get( addresses.size() - 1 );
DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, port );
//Send packet
try
{
socket.send( p );
}
catch (IOException e)
{
e.printStackTrace();
}
wait = false;
}
if( wait == true && position == true )
{
position = false;
wait = false;
}
for(int i = 0;i < positions.length; i++)
{
if(positions[i] != null)
{
//Log.d(TAG, "X and Y position of asset:"+i+", is:"+ positions[i]);
}
}
//Needs to try and reteive data...
if( wait == false )
{
//Log.d(TAG, "Waiting to retreive data");
byte[] buf = new byte[256];
packet = new DatagramPacket( buf, buf.length );
try
{
socket.receive( packet );
wait = true;
}
catch (IOException e)
{
Log.d(TAG, "Error with receiving data");
e.printStackTrace();
}
data = new String( buf, 0, packet.getLength() );
//Log.d(TAG, "Data received from :" + packet.getAddress() + ", holds this value: " + data);
String[] dataStrings = data.split(":");
if( dataStrings[0].equalsIgnoreCase( "position" ) )
{
position = true;
}
}
//Log.d(TAG, "Data received was :" + data);
/*try
{
Thread.sleep( 25 );
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
Log.d(TAG, "Error with trying to sleep");
e.printStackTrace();
}*/
}
Log.d(TAG, "Error with while run value");
return "finished";
}
public int returnPlayers(){ return players; }
}
这是客户端代码
public class gameClient extends AsyncTask<String, String, String>
{
//Variables
private static final String TAG = "gameClient";
private gameServer server;
private boolean rdyForPlay = false;
//Holds all of the over clients blocks
private gameObject[] assets = new gameObject[8];
private int ID = 0;
private int port = 50000;
private Context contextHolder;
//If this client is the host
private boolean host = false;
private DatagramSocket socket = null;
//How many clients are connected to the server
private int totalPlayers = 0;
//Constructor for gameclient
public gameClient( boolean serverTag, Context context )
{
host = serverTag;
//Client is host
if( host == true)
{
host = true;
try
{
//Start the server
contextHolder = context;
server = new gameServer( contextHolder );
this.execute();
}
catch (IOException e)
{
//Error
Log.d(TAG, "Could not start server");
e.printStackTrace();
}
}
//Client is not host
else
{
//Connect to the host
contextHolder = context;
this.execute();
}
}
//Connect to the host, to receive and send data to
public void connectToServer()
{
//Send a connect message to the server
try {
//Create a socket
socket = new DatagramSocket( port );
byte[] bufer = new byte[256];
//Send a message "connect" to the host
String msg = "connect";
int msgLength = msg.length();
bufer = msg.getBytes();
InetAddress address;
//Default ip address of the host
address = InetAddress.getByName("192.168.1.59");
DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, port );
//Send packet
socket.send( p );
} catch (UnknownHostException e2) {
Log.d(TAG, "Unknown host");
e2.printStackTrace();
} catch (SocketException e) {
Log.d(TAG, "Socket problem");
e.printStackTrace();
} catch (IOException e) {
Log.d(TAG, "I/O problem");
e.printStackTrace();
}
//Receive the message back
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket( buf, buf.length );
//Try to receive a packet from the server
try
{
Log.d(TAG, "Waiting for data");
socket.receive( packet );
}
//Error
catch (IOException e)
{
Log.d(TAG, "Error with receiving data");
e.printStackTrace();
}
//Convert the packet to a string
String data = new String( buf, 0, packet.getLength() );
//Use the string to find out what ID this client is
ID = Integer.parseInt( data );
//Setup the client game
setUpClient();
}
//Setup the client game/screen
public void setUpClient()
{
//Setup the client using the ID that was given by the host
Log.d(TAG, "ID is : " + ID);
gameObject temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.player), 250, 300);
assets[ID] = temp;
for(int i = 0; i < ID; i++)
{
temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.new_player), 50*i, 50*i);
assets[i] = temp;
}
//If this client is the host, then pass the client to the server for easy access
if( host == true )
{
server.getClientPosition( assets[ID].returnPosX(), assets[ID].returnPosY() );
}
}
//When the screen is touched
public void sendTouchEvent(float xSet, float ySet)
{
assets[ID].setPosition( xSet, ySet );
}
@Override
//Keep the game updated
protected String doInBackground(String... params)
{
//Connect to the server
if( host == false ){ while(ID == 0) { Log.d( TAG, "Client will connect to server" ); connectToServer(); } }
//If the client is host, then start the server thread
if( host == true ) { setUpClient(); server.execute(); }
//game us now ready to be played
rdyForPlay = true;
boolean run = true;
boolean setupPlayer = false;
while( run )
{
int players = 0;
//Tell the server to give position of players
//if( setupPlayer == true )
//{
// setUpClient();
// setupPlayer = false;
//}
if( host == true )
{
server.getClientPosition( assets[ID].returnPosX(), assets[ID].returnPosY() );
int newPlayers = server.returnPlayers();
if( players != newPlayers )
{
for(int i = players; i < newPlayers; i++)
{
i = i+1;
gameObject temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.new_player), 50*i, 50*i);
assets[i] = temp;
}
players = newPlayers;
}
}
//If this is a client then do this
if( host == false )
{
try {
//If the socket is not yet setup, set it up
if(socket == null)
{
socket = new DatagramSocket( port );
}
byte[] bufer = new byte[256];
//Using the ID given at the start, send X and Y position to the server
String msg = "position:" + ID +":"+ assets[ID].returnPosX() +":"+ assets[ID].returnPosY();
int msgLength = msg.length();
bufer = msg.getBytes();
InetAddress address;
address = InetAddress.getByName("192.168.1.59");
DatagramPacket p = new DatagramPacket( bufer, bufer.length , address, port );
//Send the data
socket.send( p );
Log.d(TAG, "data sent");
} catch (UnknownHostException e2) {
// TODO Auto-generated catch block
Log.d(TAG, "Error with unknown host");
e2.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
Log.d(TAG, "Error with socket");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d(TAG, "Error with sending/receiving data");
e.printStackTrace();
}
}
//Host data will ofcourse be differnet
}
Log.d(TAG, "Error with run value");
return "finished";
}
//If a new player needs to be added to the array
private void newPlayer( int idOfNewPlayer )
{
gameObject temp = new gameObject(BitmapFactory.decodeResource(contextHolder.getResources(), R.drawable.new_player), 250, 300);
assets[ idOfNewPlayer ] = temp;
}
//Update all the assets in the game
private void updateAssets()
{
}
//Return methods
public gameObject[] rtnAssets(){ return assets; }
public int rtnID(){ return ID; }
public boolean rtnRdy(){ return rdyForPlay; }
public gameServer rtnServer(){ return server; }
public boolean rtnHost(){ return host; }
//Stop the client server if host
public void stopServers()
{
if( host == true )
{
socket.close();
server.rtnSocket().close();
System.gc();
}
}
public void stopBackground()
{
socket.close();
this.cancel( true );
System.gc();
}
}
答案 0 :(得分:2)
Wheneva我们请求连接,我们将kwn一个端口号和请求。因此,尽量保持该端口免费。它可以通过使用ur系统中的其他免费端口来完成。因此,当客户端请求连接回复端口号并为该客户端分配该端口号时。由于逻辑端口太多,我们的系统可以支持高达10k的连接。所以我认为对许多用户来说这不应该是一个问题。 一旦建立连接,用户将在其分配的端口上进行通信,因此其他用户可以轻松访问您的服务器。