Java UDP支持多个连接到同一端口,发送和接收
目前,我有一个服务器,它允许客户端通过发送消息“connect”连接到它,当服务器收到此消息时,它接收InetAddress,然后使用该InetAddress向客户端发送数据,一旦客户端连接并收到其ID号,它会不断向UDP套接字发送数据,以便更新其位置,现在当新客户端想要连接时,它会发送消息“connect”,但新客户端很少会连接,现在发生的情况是,已连接的客户端使host.receive函数忙,所以当新客户端连接时,幸运的是,如果当前连接的客户端没有跳转,那么客户端只剩下一个空白屏幕 我需要的帮助是,如何支持使用同一端口的UDP套接字上的多个客户端? 所有将连接到服务器的客户端都位于同一路由器上 这是整个服务器代码Java UDP支持多个连接到同一端口,发送和接收,java,android,sockets,networking,udp,Java,Android,Sockets,Networking,Udp,目前,我有一个服务器,它允许客户端通过发送消息“connect”连接到它,当服务器收到此消息时,它接收InetAddress,然后使用该InetAddress向客户端发送数据,一旦客户端连接并收到其ID号,它会不断向UDP套接字发送数据,以便更新其位置,现在当新客户端想要连接时,它会发送消息“connect”,但新客户端很少会连接,现在发生的情况是,已连接的客户端使host.receive函数忙,所以当新客户端连接时,幸运的是,如果当前连接的客户端没有跳转,那么客户端只剩下一个空白屏幕 我需要的
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; }
}
公共类gameServer/*扩展线程*/扩展异步任务{
/**
*为Android应用程序设置服务器
*/
私有静态最终字符串TAG=“GameServer”;
专用DatagramSocket套接字;
专用int端口=50000;
私人整数玩家=0;
私有字符串[]位置=新字符串[8];
私有ArrayList地址=新ArrayList();
私有布尔等待=false;
私有上下文contextHolder=null;
//制作一个数组,此数组将保留所有位置
//发送给它的客户,
//使用ID号,它将其存储在数组块中
//而“主机”只需返回它并使用它
公共游戏服务器(上下文)引发IOException
{
//在这里,我们考虑客户区,
//这将是资产[0];
contextHolder=上下文;
套接字=新的DatagramSocket(端口);
Log.d(标记“服务器已设置”);
}
公共DatagramSocket rtnSocket(){return socket;}
私有字符串getLocalIPAddress()
{
尝试
{
对于(枚举nis=NetworkInterface.getNetworkInterfaces();nis.hasMoreElements();)
{
NetworkInterface ni=nis.nextElement();
Log.v(标记“NetworkInterface=“+ni.getDisplayName());
对于(枚举ips=ni.getInetAddresses();ips.hasMoreElements();)
{
InetAddress ip=ips.nextElement();
字符串s=ip.getHostAddress();
Log.v(标签,“InetAddress=“+s”);
如果(!ip.isLoopbackAddress())
{
if(InetAddressUtils.isIPv4Address)返回s;
}
}
}
}
捕获(SocketException e)
{
Log.e(标记“getLocalIPAddress()”,e);
}
返回null;
}
public void getClientPosition(int xPos,int yPos)
{
位置[0]=xPos+“:”+YPO;
}
@凌驾
受保护的字符串doInBackground(字符串…参数){
InetAddress客户端=null;
布尔运行=真;
字符串数据=”;
DatagramPacket数据包=null;
布尔位置=假;
while(运行)
{
if(data.equalsIgnoreCase(“”)
{
}
//发送一些数据
if(data.equalsIgnoreCase(“connect”)和&wait==true)
{
Log.d(标记“某人想要连接”);
//增加玩家总数1
玩家=玩家+1;
//向主机(客户端)通知发生了更改
//通知客户
//将带有ID的消息发送到客户端
字节[]bufer=新字节[256];
//向主机发送消息“连接”
字符串msg=Integer.toString(玩家);
int msgLength=msg.length();
bufer=msg.getBytes();
地址;
//主机的默认ip地址
//从包中取出地址
address.add(packet.getAddress());
Log.d(标记“Address is”+addresses.get(addresses.size()-1));
address=addresses.get(addresses.size()-1);
DatagramPacket p=新的DatagramPacket(bufer,bufer.length,address,port);
//发送数据包
尝试
{
socket.send(p);
}
捕获(IOE异常)
{
e、 printStackTrace();
}
等待=错误;
}
if(wait==true&&position==true)
{
位置=假;
等待=错误;
}
对于(int i=0;ipublic 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();
}
}