ユーザーの入力をサーバーに投稿するだけのAndroidソケットデモを作成します。Wi-Fi接続を介してAndroidクライアントからソケットを確立すると、すべてがうまくいき、サーバーは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);
}
}
サーバーのコード:
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 電話ではソケットが例外なく書き込みを行うことができます。どのタイプの電話でもソケット接続が切断されたことを知るにはどうすればよいですか?
任意の提案をいただければ幸いです。
ps Connective Change Broadcast は知っていますが、ブロードキャストを受信する前に、クライアントが壊れたソケットを介して何らかのメッセージを書き込んでいる可能性があります。
アプリケーション プロトコルに受信チェックを追加することでメッセージ損失の問題を解決できますが、私は TCP プロトコルが約束するトランスポート層での信頼性を保証することを好みます。