如何使用 TCP 将相同的数据发送到多部 Android 手机?
这是我刚才问的一个问题的“现在进一步”扩展...我现在对套接字有了更好的理解,并且有一些工作代码,但需要改进它...
好吧,所以我目前已经使用 UDP 多播来将短文本字符串从 Java“服务器”应用程序发送到几部 Android 手机(可能会成为数百部 Android 手机)。这在大多数情况下工作得很好,但它确实往往会丢失奇数电话上的奇数字符串,并且随机地它会在短时间内完全丢失,并且任何一个都无法接通,这可能有点令人沮丧。
据我了解,因为无法在 TCP 上进行广播 - 我的想法是让手机最初使用 ServerSocket“连接”到服务器应用程序。这只会收集客户端 IP 地址,这些地址将存储在名为 clients 的 Set
中。然后我想要迭代这些地址并将字符串分别发送到每部手机 - 但是我不想阻止代码,也不想永远等待发送发生,如果,比如说,手机已进入睡眠状态,无法/不会接受连接。信息需要在开始发送后几秒钟内到达所有电话(即使有 2-300 个客户端)。
我的初始代码如下,我对此的疑问是:
- 这个代码在一个线程中足够吗?
- 现代CPU会很好地利用多个线程,并将地址集均匀地分配在它们之间(比如4个线程吗?)
- (正如我相信的那样)在自己的线程中旋转每个连接/发送是一个坏主意吗?
- 设置套接字超时是否允许线程更快地处理其列表?或者这会引起问题吗?
- 如果套接字超时设置是个好主意,那么合理的时间是多少?或者我是否需要进行测试才能得到正确的结果?
预先感谢你们提供的任何帮助...
for (InetAddress client : clients) {
try {
Socket sendQuestionSocket = new Socket(client, portSend);
// Theory: 50 milliseconds is enough to connect, and could allow 200 clients
// to get their questions in around 10 seconds. Maybe?
sendQuestionSocket.setSoTimeout(50);
PrintWriter outStream = new PrintWriter(sendQuestionSocket.getOutputStream());
outStream.println(question.toString());
outStream.flush(); // Do I need this line?
sendQuestionSocket.close();
outStream.close();
} catch (InterruptedIOException e) {
logger.log(Level.WARNING, "Couldn't connect in time... passing this one over");
e.printStackTrace();
} catch (UnknownHostException e) {
logger.log(Level.SEVERE, "Unable to find that client");
e.printStackTrace();
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to create question sending port");
e.printStackTrace();
}
}
This is a bit of a "further down the track now" extension to a question I asked a while ago... I have a better understanding of sockets now, and have some working code but need to improve it...
Ok, so I have currently got UDP multicasting working to send short strings of text from a Java 'server' application to several Android phones (which will potentially become several hundred Android phones). This works fine most of the time, but it does tend to lose the odd string on the odd phone, and randomly it will just go total loss for a short period and nothing will get through to any of them, which can be a little frustrating.
Since, as I understand, there is no way to broadcast on TCP - my idea is to have the phones initially 'connect' to the server app using a ServerSocket. This will do nothing more than harvest client IP addresses which are to be stored in a Set<InetAddress>
called clients. Then I will want to iterate over these addresses and send the string to each phone individually - but I don't want to block the code, nor do I want to spend forever waiting for sends to occur if, say, the phone has gone to sleep and can't / won't accept connections. The information will need to get to all phones within a few seconds of starting to send (even with 2-300 clients).
My initial code is below, and the questions I have regarding it are:
- Is this code in one thread enough?
- Would a modern CPU make good use of several threads with the address set split evenly amongst them (say 4 threads?)
- Is it (as I believe) a bad idea to spin every connection/send off in its own thread?
- Does setting the socket timeout allow the thread to work through its list faster? Or will this cause problems?
- If socket timeout setting is a good idea, then what is a sensible time? Or do I need to just test to get this right?
Thanks in advance for any help you guys can provide...
for (InetAddress client : clients) {
try {
Socket sendQuestionSocket = new Socket(client, portSend);
// Theory: 50 milliseconds is enough to connect, and could allow 200 clients
// to get their questions in around 10 seconds. Maybe?
sendQuestionSocket.setSoTimeout(50);
PrintWriter outStream = new PrintWriter(sendQuestionSocket.getOutputStream());
outStream.println(question.toString());
outStream.flush(); // Do I need this line?
sendQuestionSocket.close();
outStream.close();
} catch (InterruptedIOException e) {
logger.log(Level.WARNING, "Couldn't connect in time... passing this one over");
e.printStackTrace();
} catch (UnknownHostException e) {
logger.log(Level.SEVERE, "Unable to find that client");
e.printStackTrace();
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to create question sending port");
e.printStackTrace();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会在这里使用线程:每个客户端一个线程。对于现代CPU来说这是可以的,并且不会让你阻塞执行。因此,即使有很多死客户端,活客户端也会尽快得到答案。
I would go with threads here: one thread for every client. It is ok for modern cpu, and it won't make you block for execution. So, the live clients will get the answer as soon as possible even if there are a lot of dead clients.
我不确定你想做的事情是否有效。 ServerSocket 不允许您收集远程 IP 地址并在需要时重新连接。为了连接回这些设备,它们必须有一个服务器侦听特定端口并接受您的传入连接。
因为看起来你已经有客户端连接到你的服务器套接字,所以我只会告诉他们连接后需要知道的一切 - 除非你真的可以在每部手机上都有一个服务器。
另一种选择是使用(无连接)UDP,但客户端代码仍然必须主动等待数据报包。
当在 Java 中做任何与 Socket 相关的事情时,我强烈推荐 Netty。 Netty 将为您处理所有异步网络 IO,让您专注于客户端连接后要做的事情。
I'm not sure what you're trying to do will work. ServerSocket is not there to allow you to gather remote IP addresses and just connect back when you want. In order to connect back to those devices they would have to have a server listening on a particular port and accept your incoming connection.
Since it seems like you already have the clients connecting to your server socket i would just tell them whatever they need to know once they have connected - unless you really can have a server on each phone.
Another option would be to use (connectionless) UDP but the client code would still have to be actively waiting for datagram packets.
When doing anything Socket related in Java i highly recommend Netty. Netty will handle all the asynchronous network IO for you and let you focus on what to do once the client has connected.