我写了一个Android套接字演示,它只是将用户的输入发送到服务器。我从android客户端通过wifi连接建立了一个socket,一切顺利,服务器可以接收android客户端发送的消息。问题是,然后我关闭了手机的WIFI,但插座可以无一例外地写入。
Android客户端代码:
public class MyActivity extends Activity {
private SocketHandlerThread thread;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
thread = new SocketHandlerThread("ScoketTest");
thread.start();
}
class SocketHandlerThread extends HandlerThread {
private Socket socket;
private Handler handler;
public SocketHandlerThread(String name) {
super(name);
}
public SocketHandlerThread(String name, int priority) {
super(name, priority);
}
@Override
public void run() {
try {
socket = new Socket("192.168.60.184", 1990);
} catch (IOException e) {
Log.e("SocketTest", e.getLocalizedMessage(), e);
}
super.run();
}
Handler getHandler() {
if (handler == null) {
handler = new Handler(getLooper());
}
return handler;
}
void send(final String text) {
Runnable runnable = new Runnable() {
public void run() {
Log.e("SocketTest", "Start send text: " + text);
try {
socket.getOutputStream().write((text + "\n").getBytes());
socket.getOutputStream().flush();
} catch (Exception e) {
Log.e("SocketTest", e.getLocalizedMessage(), e);
}
Log.e("SocketTest", "Text has been send:" + text);
}
};
getHandler().post(runnable);
}
@Override
protected void onLooperPrepared() {
runOnUiThread(new Runnable() {
@Override
public void run() {
findViewById(R.id.button).setEnabled(true);
}
});
}
}
public void send(View view) {
String text = ((EditText) findViewById(R.id.text)).getText().toString();
thread.send(text);
}
}Server的代码:
public class SocketTestServer {
ServerSocket serverSocket;
SocketTestServer() throws IOException {
serverSocket = new ServerSocket(1990);
}
void start() throws IOException {
Socket clientSocket = serverSocket.accept();
clientSocket.getInputStream();
PrintWriter out = new PrintWriter(System.out, true);
BufferedReader in =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
}
public static void main(String[] args) throws IOException {
SocketTestServer server = new SocketTestServer();
server.start();
}
}我试了几部手机。在Galaxy Nexus(4.2.1)上,正如预期的那样抛出了一个异常,但在一些MOTO或HTC手机上,socket仍然可以写入,没有任何异常,这意味着我可能会丢失一些我认为已经成功接收的消息。我如何才能知道任何类型的电话上的插座连接都断开了?
任何建议都将不胜感激。
附注:我知道连接更改广播,但在收到广播之前,客户端可能已经通过损坏的套接字写入了一些消息。
虽然在应用协议上增加接收校验可以解决报文丢失的问题,但我更倾向于在传输层上保证TCP协议所承诺的可靠性。
发布于 2013-01-07 16:54:55
我在我的套接字中使用Writer和IOException,它工作得很好。试试这个:
public static void sendUTF(String str)
{
try
{
outWriter.write(str + '\n');
outWriter.flush();
}
catch (IOException e)
{
e.printStackTrace();
outServ.setText("Connection lost!");
}
}
public static Writer outWriter = new OutputStreamWriter(outputStream, "UTF-8");发布于 2013-01-19 06:25:48
这是TCP堆栈(OS级别)的一个问题,也是一个难以解决的问题。如果服务器断开了连接,也会发生这种情况(尝试在打开套接字后重新启动服务器,客户端将不会注意到)……下次通过套接字发送数据包时,您将遇到“管道断开错误”。
因此,有两种情况:
1-客户端发送信息时管道断开。
在这种情况下,您应该捕获IOException并重试打开连接(您必须定义重试策略)。
2-服务器断开连接时管道断开
当服务器断开连接时,客户端不会注意到这一点,在这种情况下,您应该定期向服务器发送数据包(轮询技术),并尝试重新连接,以防连接丢失。这只在您从服务器接收更新时才需要,如果您的流量始终是客户端-->服务器,则仅适用于场景1。
https://stackoverflow.com/questions/14191934
复制相似问题