1

目前我有一个服务器,它将允许客户端通过发送消息“连接”来连接它,当服务器收到此消息时,它会接收 InetAddress,然后使用该 InetAddress 向客户端发送数据,一旦客户端已连接并收到其 ID 号,它将不断向 UDP 套接字发送数据,以便它可以更新其位置,现在当新客户端想要连接时,它会发送消息“连接”,但很少有新客户端会连接,发生的事情是已经连接的客户端一直保持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();
}
}
4

1 回答 1

2

当我们请求连接时,我们将知道一个端口号并请求。因此,请尽量保持该端口空闲。这可以通过使用您系统中的其他免费端口来完成。因此,当客户端请求连接时,回复一个端口号并为该客户端分配该端口号。由于逻辑端口众多,我们的系统最多可支持 10k 连接。所以我认为这对许多用户来说不应该是一个问题。一旦建立连接,用户将在分配给它的端口上进行通信,因此其他用户可以轻松访问您的服务器。

于 2013-04-03T16:42:28.337 回答