前言:最近在调研localonlyhotspot(本地热点),需要写一个demo来证明可以通过热点实现socket通信。经历重重波折终于搞定了,在这里做一个总结。
源码下载
下面直接看代码:
服务端代码:
开启socket
public void click2(View view) {
new Thread() {
ServerSocket serverSocket = null;
@Override
public void run() {
try {
serverSocket = new ServerSocket(9999);
}catch (Exception e) {
Log.d("server is fail" , e.getMessage());
}
if (serverSocket != null) {
while (true) {
Log.d("click2" , "socket success");
try {
Socket client = serverSocket.accept();
new HandlerThread(client);
}catch (IOException e) {
Log.d("click2", "socket1 IOException");
}
}
}
}
}.start();
}
服务端发送消息
private class HandlerThread implements Runnable {
private Socket socket;
public HandlerThread(Socket client) {
socket = client;
new Thread(this).start();
}
public void run() {
try {
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
clientInputStr = input.readLine();
PrintStream out = new PrintStream(socket.getOutputStream());
String s = "I an server";
Log.d("HandlerThread" , clientInputStr);
out.println(s);
out.close();
input.close();
} catch (Exception e) {
Log.d("server run" , e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (Exception e) {
socket = null;
Log.d("HandlerThread run" , e.getMessage());
}
}
}
}
}
客户端代码
客户端socket建立时需要服务端的IP地址,这个我专门写了一个api,在前面博客里,可以直接用。
服务端IP地址的获取方法
创建socket并发送消息给服务端:
public void click(View view) {
Thread connectThread = new Thread() {
BufferedReader input = null;
PrintStream out = null;
@Override
public void run() {
Log.d(TAG , "socket123");
Socket socket = null;
try {
socket = new Socket(ipAddress,PORT);
Log.d(TAG , "socket123");
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintStream(socket.getOutputStream());
if (!socket.isConnected()) {
Log.d(TAG, "socket is not connected!!");
out.close();
input.close();
} else {
String str = "I am client";
out.println(str);
ret = input.readLine();
if (ret != null) {
Log.d("client",ret );
}
}
} catch (Exception e) {
Log.d(TAG , e.getMessage());
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
socket = null;
Log.d(TAG , e.getMessage());
}
}
}
}
};
connectThread.start();
}
注意点:
1、客户端一定要新起一个线程去创建socket,不然会报错。
2、开启热点需要定位权限,不仅仅Androidmainfest.xml里要加,还有动态获取。
3、服务端IP地址需要服务端告诉客户端,客户端获取不到。
4、使用startLocalOnlyHotspot打开热点,每次关闭热点需要创建一个守护线程来保存mLocalOnlyHotspotReservation的值,否则下次再次打开热点,上一次的mLocalOnlyHotspotReservation会被回收,就会导致热点在后台时被关闭。
5、每次打开热点会随机生成ssid和password,每次都不一样。