使用服务的 TCP 连接
TCP Connection using Service
我必须实施一个应用程序。此应用程序使用 TCP/IP 与服务器通信。我的应用程序必须向 server.Because 请求位置,应用程序必须留下来监听服务器请求,我想使用 IntentService。所以我实现了它:
public class Tasks extends IntentService{
public final int SERVERPORT = 8100;
private Socket socket;
PrintWriter out;
BufferedReader in;
public Tasks()
{
super("My task!");
}
protected void onHandleIntent(Intent intent)
{
try
{
InetAddress serverAddr = InetAddress.getByName("10.0.0.138");
socket = new Socket(serverAddr, SERVERPORT);
out = new PrintWriter(socket.getOutputStream());
//send the request to authenticate it
out.print("Hello man");
out.flush();
//now i need to receive the request Hello_ACK
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String mServerMessage = in.readLine();
if(mServerMessage.equals("Hello_ACK"))
Log.d("show","connection completed");
//now how can I send KEEP_ALIVE message to server?
out.print("KEEP_ALIVE");
out.flush();
}
catch (IOException e)
{
e.printStackTrace();
} } }
我想问你几个问题:
1. IntentService如何维护与服务器的TCP连接?
2. 每 5 分钟我必须向服务器发送 "KEEP_ALIVE" 消息..我该怎么说呢?
3.I已执行此任务以保持与服务器的连接;为了在服务器上调用位置,我是否要使用新线程(例如,新的 class extends Runnable)?
4. 使用 asynctask 做同样的工作是错误的吗?
5.为了与主UT通信,我必须实现一个RegisterReceiver,这是错误的吗?
感谢您的帮助。
阅读您的说明后:
使用 IntentService
本身就可以了。请注意,IntentService
创建了一个工作线程来处理传入的意图。
在您的服务启动时或在您第一次收到 Intent
时懒惰地创建套接字。不要像现在这样每次收到新的意图时都 reconnect/recreate 套接字。只需重新使用现有的套接字即可。但是,您可能希望在连接断开时添加对重新连接套接字的支持(即当您获得 IOError
时)。延迟创建套接字可能更可取,因为您将在 correct 线程(即意图处理程序线程)中执行此操作。见下文。
您不需要单独的线程来等待传入数据。只需在您已经免费获得的意图处理程序线程中执行此操作即可。传入的意图将排队,您的服务将一个接一个地处理它们。
AsyncTask
对很多人来说有点混乱。与 postDelayed()
不同,AsyncTasks 是真正的后台操作,带有用于同步框架操作的附加挂钩。最初,AsyncTasks 在单独的线程中异步执行。 DONUT introduced a thread pool and HONEYCOMB 回到单线程以避免常见的竞争条件。
服务有点不同。创建新服务并不意味着该服务在其自己的线程中 运行。相反,对于典型的用例,正在创建的 main Activity
和新创建的 Service
共享同一个线程,等待传入的消息。在 UI 线程上进行阻塞(例如网络 IO)操作肯定会使您的应用程序无响应(这就是为什么 Android prevents it by default)。
对于 keep-alives,您可以简单地在您的服务中使用 Handler.postDelayed()
。 (参见 Android run a Task Periodically)。如果您在 Intent 处理程序线程(即 IntentService
为您创建的线程)上创建处理程序,您甚至不必担心并发访问。
从您的服务向任何意向发件人发送回复的最简单方法是使用 Context.sendBroadcast()
。要使用它,请使用 Context.registerReceiver()
为您的 Activity
注册一个 BroadcastReceiver
。 BroadcastReceiver
将接收所有匹配过滤器的 Intent
。通常的方法是为 Intent
想出一个唯一的动作名称并以此进行过滤。
[编辑] 更正关于 AsyncTask
处理的声明。
我必须实施一个应用程序。此应用程序使用 TCP/IP 与服务器通信。我的应用程序必须向 server.Because 请求位置,应用程序必须留下来监听服务器请求,我想使用 IntentService。所以我实现了它:
public class Tasks extends IntentService{
public final int SERVERPORT = 8100;
private Socket socket;
PrintWriter out;
BufferedReader in;
public Tasks()
{
super("My task!");
}
protected void onHandleIntent(Intent intent)
{
try
{
InetAddress serverAddr = InetAddress.getByName("10.0.0.138");
socket = new Socket(serverAddr, SERVERPORT);
out = new PrintWriter(socket.getOutputStream());
//send the request to authenticate it
out.print("Hello man");
out.flush();
//now i need to receive the request Hello_ACK
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String mServerMessage = in.readLine();
if(mServerMessage.equals("Hello_ACK"))
Log.d("show","connection completed");
//now how can I send KEEP_ALIVE message to server?
out.print("KEEP_ALIVE");
out.flush();
}
catch (IOException e)
{
e.printStackTrace();
} } }
我想问你几个问题: 1. IntentService如何维护与服务器的TCP连接? 2. 每 5 分钟我必须向服务器发送 "KEEP_ALIVE" 消息..我该怎么说呢? 3.I已执行此任务以保持与服务器的连接;为了在服务器上调用位置,我是否要使用新线程(例如,新的 class extends Runnable)? 4. 使用 asynctask 做同样的工作是错误的吗? 5.为了与主UT通信,我必须实现一个RegisterReceiver,这是错误的吗? 感谢您的帮助。
阅读您的说明后:
使用
IntentService
本身就可以了。请注意,IntentService
创建了一个工作线程来处理传入的意图。在您的服务启动时或在您第一次收到
Intent
时懒惰地创建套接字。不要像现在这样每次收到新的意图时都 reconnect/recreate 套接字。只需重新使用现有的套接字即可。但是,您可能希望在连接断开时添加对重新连接套接字的支持(即当您获得IOError
时)。延迟创建套接字可能更可取,因为您将在 correct 线程(即意图处理程序线程)中执行此操作。见下文。您不需要单独的线程来等待传入数据。只需在您已经免费获得的意图处理程序线程中执行此操作即可。传入的意图将排队,您的服务将一个接一个地处理它们。
AsyncTask
对很多人来说有点混乱。与postDelayed()
不同,AsyncTasks 是真正的后台操作,带有用于同步框架操作的附加挂钩。最初,AsyncTasks 在单独的线程中异步执行。 DONUT introduced a thread pool and HONEYCOMB 回到单线程以避免常见的竞争条件。服务有点不同。创建新服务并不意味着该服务在其自己的线程中 运行。相反,对于典型的用例,正在创建的 main
Activity
和新创建的Service
共享同一个线程,等待传入的消息。在 UI 线程上进行阻塞(例如网络 IO)操作肯定会使您的应用程序无响应(这就是为什么 Android prevents it by default)。对于 keep-alives,您可以简单地在您的服务中使用
Handler.postDelayed()
。 (参见 Android run a Task Periodically)。如果您在 Intent 处理程序线程(即IntentService
为您创建的线程)上创建处理程序,您甚至不必担心并发访问。从您的服务向任何意向发件人发送回复的最简单方法是使用
Context.sendBroadcast()
。要使用它,请使用Context.registerReceiver()
为您的Activity
注册一个BroadcastReceiver
。BroadcastReceiver
将接收所有匹配过滤器的Intent
。通常的方法是为Intent
想出一个唯一的动作名称并以此进行过滤。
[编辑] 更正关于 AsyncTask
处理的声明。