I am trying to put together a basic Java proof-of-concept to have a server (which will most likely just be a Windows or Linux laptop) that can send messages to a number of WIFI-connected android devices on the same subnet (initially 20-30, but it could be quite a number in the future - 2 or 300? - not sure, but I need to allow for the possibility). The app will send a message to all devices (the same message initially - but I may allow for special cases somewhere down the track). Each device can then reply, and I will want to check which ones replied and store the replies.
I tried some test code using UDP (with some help from a tutorial on nakov.com), but it was very unreliable and the phone often locked up while trying to receive a packet - although it worked perfectly sometimes. My client code for the android device is shown below for reference (note, this code just sends a request for a message, and then receives and displays it - I hadn't got around to writing it the way I wanted it since it didn't seem reliable enough to use anyway).
So, I think I probably need to use TCP for reliability (although I am open to suggestions). Would 2-300 individual TCP concurrent connections be ok? And its likely that all the replies would come in to the server at once (or over a 10-15 second period), would this flood it in a way it couldn't handle? Is it likely to be ok for only 20-30 devices?
I know this is a kind of out-there question, but I'm hoping someone with more understanding of TCP than I have can shed some light and give me some pointers.
Cheers
Steve
UDP Client App:
package nz.co.et.quoteclient;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class QuoteClient extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)开发者_如何学Python;
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.Button01);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifiManager.isWifiEnabled()) {
TextView errorText = (TextView) findViewById(R.id.TextView01);
int serverPort = 4445;
InetAddress address = null;
try {
address = InetAddress.getByName("192.168.1.4");
} catch (UnknownHostException e) {
errorText.setText("Failed at setting server IP Address");
e.printStackTrace();
}
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, serverPort);
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
} catch (SocketException e) {
errorText.setText("Failed at creating socket");
e.printStackTrace();
}
try {
socket.send(packet);
} catch (IOException e) {
errorText.setText("Failed at sending request packet");
e.printStackTrace();
}
// get response
packet = new DatagramPacket(buf, buf.length);
try {
socket.receive(packet);
} catch (IOException e) {
errorText.setText("Failed at receiving quote packet from server");
e.printStackTrace();
}
// display response
String message = new String(packet.getData());
String data = "";
for (int i = 0; i < message.length(); i++) {
int tmp = (int) message.charAt(i);
data = (tmp <= 0 || tmp >= 256) ? data += "" : data + message.charAt(i);
}
Toast.makeText(getApplicationContext(), data, Toast.LENGTH_LONG).show();
// errorText.setText(data);
}
else {
Toast.makeText(getApplicationContext(), "WIFI not enabled", Toast.LENGTH_LONG).show();
}
}
});
}
}
TCP is certainly going to be more reliable than UDP, since UDP doesn't guarantee packet delivery (which is probably why you application is hanging on the receive).
2-300 connections should be managable, but it's going to depend on things like your hardware capabilities and the amount of data that's being processed / sent back and forth.
You're also going to have to make a few decisions around things like:
What language are you writing your server in (java?)?
Do you maintain a persistent connection from the client to the server, or recreate it each time?
Who is responsible for establishing the connection (the client or the server)?
How is the server going to identify which device has received the message, is it tied to the ip address, or is there some kind of handshaking going on to identify the clients.
If a client becomes connected do you need to send all previously missed information?
Does the information need to get to all of the clients at the same time, or can it be staggered?
How does your client app behave if it loses connection, does it retry etc?
And the list goes on...
Depending upon how your program your server, you ought to be able to handle a few thousand concurrent TCP sessions.
If you pick threading, you might not be able to scale beyond 100-or so clients; each thread brings along enough per-thread storage and scheduling overhead that I really wouldn't want to count on it beyond 50 clients.
The new Java NIO framework provides some of the functionality that can be used to scale into hundreds or thousands of simultaneous connections. If the framework uses select(2)
under the hood, it ought to be able to do upwards of 1000 simultaneous connections, but if it uses epoll(2)
or kqueue
or similar constructs, then even beyond 1000 simultaneous connections should be feasible.
What you do with those sessions might dictate far smaller numbers of simultaneous connections: streaming video will be more intensive than sending a nice polite "welcome to our network" page.
精彩评论