当socket中有数据可供读取时,android中是否有回调机制
嗯,我熟悉 c、iOS 环境中的套接字编程。但是现在尝试通过套接字连接我的 android 和远程服务器...作为启动,我用 C 编写了一个简单的服务器程序,并在我的桌面上运行它耐心等待连接请求,接受连接,然后等待一些请求字符串,在获取请求字符串时返回一些响应字符串,然后再次等待下一个请求并继续..好吧,你明白了..
到目前为止
- 我已经与我的 android 建立了连接,服务器
- 发送和接收数据
这是我的客户端代码..
public class SocketMaster {
private Socket clientSocket = null;
BufferedReader socketReadStream = null;
public boolean connectToHost(String ip, int port){
try {
InetAddress serverAddr = InetAddress.getByName(ip);
try {
clientSocket = new Socket(serverAddr, port);
socketReadStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
String stringToSend = "This is from client ...Are you there???";
//Write to server..stringToSend is the request string..
this.writeToServer(stringToSend);
//Now read the response..
while((line = socketReadStream.readLine()) != null){
Log.d("Message", line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
} catch (UnknownHostException e) {
e.printStackTrace();
return false;
}
return true;
}
public boolean writeToServer(String stringToSend){
DataOutputStream dos = null;
try {
dos = new DataOutputStream(clientSocket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
return false;
}
try {
dos.write(stringToSend.getBytes());
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
}
我从另一个活动创建一个 SocketMaster 对象,并调用 connectToHost 传递服务器的 ip 和端口..一切正常,我能够连接、发送和接收数据..
现在我的问题是关于这些行
//Now read the response..
while((line = socketReadStream.readLine()) != null){
Log.d("Message", line);
}
从我的理解,执行此代码的线程
- 会阻塞,直到有数据要读取,
- 如果有数据可用,则读取它,然后因为循环再次阻塞,直到 下一个数据块到达
只是我无法在主线程上运行此代码,因为它会阻止我的 UI 活动..我可以考虑在后台线程中运行此代码,这是一个选择...
但理想情况下我想要的是。 ..
回调(我认为,Android 术语中的听众,任何熟悉 iOS CFSocket 和 callback),method ,当有数据可供读取时会调用该方法,以便我可以读取数据然后返回..
android/ java 中是否有这样的机制...如果没有(:-( ),任何人都可以将我链接到一些在后台完成套接字处理的示例...
编辑: 我不是在问自己创建一个回调机制。我只是问是否有任何侦听器存在,当有数据要读取、连接断开时通知您。因此我可以消除上面给出的 while 循环...如果没有任何回调,我准备将此套接字移动到另一个线程,该线程循环并读取数据(事实上我已经完成了)...
**
再次编辑赏金时间..
**
好吧,我是 2 弱者老 android/java 开发人员,拥有良好的 3.5多年的c/c++/objective c开发经验背后......所以我看到了低级c本机套接字(当使用read()和recv()时阻塞(可配置))和苹果的CFSocket(它是C套接字本身,但提供一个包装器来提供回调机制).. 我不是在询问自己在这里编写回调机制(如果没有现成的替代方案,我全心全意地准备这样做,但为什么要重新发明轮子又来了?)...我要开始了将java理解为非常先进和高级的平台..我认为应该潜伏着一些更高级别的包装库..所以我正在考虑通过启动赏金来增加该线程的受众..
Well I am familiar with socket programming in c, iOS environment..But now trying to connect my android and my remote server via sockets...As a start up, I wrote a simple server program in C and ran it on my desktop which patiently wait for a connection request, accepts connection, then wait for some request string, and on getting the request string returns some response string, then again wait for next request and go on..Well you get the idea..
So far
- I have established a connection with my android and server
- sent and received data
And this is my client code..
public class SocketMaster {
private Socket clientSocket = null;
BufferedReader socketReadStream = null;
public boolean connectToHost(String ip, int port){
try {
InetAddress serverAddr = InetAddress.getByName(ip);
try {
clientSocket = new Socket(serverAddr, port);
socketReadStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
String stringToSend = "This is from client ...Are you there???";
//Write to server..stringToSend is the request string..
this.writeToServer(stringToSend);
//Now read the response..
while((line = socketReadStream.readLine()) != null){
Log.d("Message", line);
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
} catch (UnknownHostException e) {
e.printStackTrace();
return false;
}
return true;
}
public boolean writeToServer(String stringToSend){
DataOutputStream dos = null;
try {
dos = new DataOutputStream(clientSocket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
return false;
}
try {
dos.write(stringToSend.getBytes());
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
}
I create an object of SocketMaster from another activity and calls connectToHost passing ip and port of server..Everything works fine and I am able to connect, send and receive data..
Now my question is regarding these lines
//Now read the response..
while((line = socketReadStream.readLine()) != null){
Log.d("Message", line);
}
From what I understand, the thread that executes this code
- blocks until there is data to read
- if data available, read it, then because of loop again blocks until
next chunk of data arrives
Simply I can't run this code on main thread as it will block my UI Activities..I can think of running this in a background thread, which is one option...
But Ideally what I want is...
A callback (I think, listener in android terms, anyone familiar with iOS CFSocket and callback),method , which gets called when there is data available to read, so that I can just read data and then return..
Is there any such mechanism in android/ java...If not ( :-( ), can anyone link me to some example where socket handling is done in background...
EDIT:
I was not asking about creating a callback mechanism myself..I was just asking is there any listener present which notify you when there is data to read, when the connection got disconnected..Thus I can eliminate the above given while loop...If there isn't any callback, I am ready move this socket to another thread, which loops arounds and reads data (which infact I have already done)...
**
EDIT Bounty time again..
**
Well I am 2 weak old android/java developer with a good 3.5 years of c/c++/objective c development experience behind that... So I have seen low level c native sockets (which blocks(configurable) when use read() and recv()) and apple's CFSocket (which is C socket itself but provide a wrapper to provide callback mechanism).. I am not asking about coding a callback mechanism myself here (which I am whole heartedly ready to do if there is no readymade alternative present, but why reinvent the wheel again?)...I am beginning to understand java as very advanced and high level platform.. I thought there should be some higher level wrapper library lurking around..So I am thinking of increasing the audience to this thread by starting a bounty..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Java 中没有现成的回调。您可以使用 NIO 包中的类轻松实现一个。您主要需要 Selector 和 SocketChannel。如果您熟悉 select(2),应该很容易理解。如果没有,请尝试 NIO 教程。
http://download.oracle.com/javase/1.5。 0/docs/api/java/nio/channels/SocketChannel.html
http://download.oracle.com/javase/1.5.0/docs/api/java/nio/channels/Selector.html
在任何情况下,您都必须轮询套接字以检查是否有数据,并且您可以不要在主线程上执行此操作。除非您的 Android 应用程序应该在同一线程上管理多个连接,否则仅使用阻塞 IO 可能会容易得多。另一件需要考虑的事情是:如果必须连续/长时间运行,您需要将其移动到服务中。即使如此,如果操作系统耗尽资源,操作系统也可以杀死它,因此请准备好处理重新连接。
华泰
There is no ready-made callback for this in Java. You can easily implement one using the classes in the NIO package. You mostly need Selector and SocketChannel. If you are familiar with select(2), should be easy to follow. If not, try a NIO tutorial.
http://download.oracle.com/javase/1.5.0/docs/api/java/nio/channels/SocketChannel.html
http://download.oracle.com/javase/1.5.0/docs/api/java/nio/channels/Selector.html
In any case, you will have to poll the socket to check if there is data, and you can't do this on the main thread. Unless your android app should manage multiple connections on the same thread, it might be a lot easier to just use blocking IO. Another thing to consider: if this has to run continuously/for a long time you need to move it to a service. Even then, the OS can kill it, if it runs out of resources, so be ready to handle reconnects.
HTH
您可以尝试以下操作:
在 java 中定义一个处理程序,如下所示
现在定义一个处理网络操作的类:
在您的 UI 线程或其他地方使用 onReceive 方法
Here is something you can try:
Define a handler in java like this
Now define a class that handles networking operations:
On your UI thread or elsewhere use the method onReceive as
如果您正在寻找使用服务来管理后台长期连接的 Android 应用示例,请查看 ConnectBot:
http://code.google.com/p/connectbot/source/browse/
它使用服务来管理终端连接。然而,这是一组非常复杂的代码,可能需要一些挖掘才能找出您想要使用的位。
大多数人通过 HTTP 进行服务器连接,并且请求上下文和回调之间存在一对一的映射。因此,我们可以使用 IntentService 来处理后台请求,并传入 ResultReceiver 来让服务在请求完成/失败时回调到 UI 线程:
http://developer.android.com/reference/android/os/ResultReceiver.html
相同的通用技术应该长期适用- 运行套接字连接,尽管您可能必须选择不同形式的服务,以便您可以自己管理生命周期。但如果这样做,您应该能够将 ResultReceiver 的意图作为重新排队的一部分,将其排队等待处理,然后在 ResultReceiver 上使用 send() 将回调发送到 UI。
If you're looking for a sample of an Android app that uses a service to manage background long-term connections, check out ConnectBot:
http://code.google.com/p/connectbot/source/browse/
It uses a service to manage terminal connections. It's a very complex set of code however, probably take some digging to figure out the bits you want to make use of.
Most folks do server connections via HTTP, and there's a one-to-one mapping between request contexts and callbacks. So we can get away with an IntentService to handle backgrounding the requests, and pass in a ResultReceiver to get the service to call back to the UI thread when the request is completed/failed:
http://developer.android.com/reference/android/os/ResultReceiver.html
The same general technique should apply for long-running socket connections, though you'll probably have to opt for a different form of service so that you can manage the lifecycle on your own. But if you do, you should be able to take an intent in with a ResultReceiver as part of the requeue, queue it up for processing, and then send() on the ResultReceiver to get the callback out to the UI.