首先,网络操作一定不能在主线程里操作,这和修改UI是相反的,修改UI一定要在主线程里。
服务端:
1.开启一个服务,在服务里开启线程来操作网络;
2.创建ServerSocket,制定本地地址的监听接口;
3.使用ServerSocket.accept获得客户端的Socket;
4.在while里再开启线程,再在里面用Socket创建读取和写入的流工具;
5.再创建一个while,持续地读取socket里的内容,实现监听;
6.循环结束时,比如客户端断开,或服务端断开,关闭流工具,关闭Socket。
客户端:
1.创建线程,在线程里创建套接字Socket,指明要访问的服务器地址;
2.在线程里创建读取和输入流工具;
3.创建while,在循环里持续读取socket里的数据,实现监听;(1-3在同一线程内完成,第三步也可以单独开线程完成,推荐顺便写在一个线程里)
4.用户选择发送数据,创建线程发送;
5.退出时关闭socket,流工具。
相关问题:
当线程或者服务处理完相关事物后需要更改UI,可以通过异步或者发送广播来让主线程更新UI。
可以通过设置标记位来防止重复请求连接和监听连接状态。
记得服务也是跑在主线程里的;服务端可以持续监听来自客户端的信息,却没有办法持续监听自己的输出,自己返回给客户端的信息必须是即时开始,即时结束。
流工具:
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(new BufferedReader(new OutputStreamWriter(socket.getOutputStream())),true); 第二个参数是自动flush
其实套接字也可以实现跨设备通信,只是对于获得设备的IP地址比较复杂,设备的IP地址和类型是会改变的,而且有些安卓系统经过厂商的改造后,IP地址不好获得,所以还是使用创建一个服务器来代理数据的传输比较好用。
获得设备地址的代码:
public static String getIPAddress(Context context){
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); if (info != null && info.isConnected()){ if (info.getType() == ConnectivityManager.TYPE_MOBILE){ //移动网路 try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { return inetAddress.getHostAddress(); } } } }catch (SocketException e){ e.printStackTrace(); } } }else if (info.getType() == ConnectivityManager.TYPE_WIFI){ WifiManager wifiMananger = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiMananger.getConnectionInfo(); String ipAddress = intIP2StringIP(wifiInfo.getIpAddress()); return ipAddress; }else { Toast.makeText(context,"没有网络可用",Toast.LENGTH_LONG); } return null; } public static String intIP2StringIP(int ip) { return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + (ip >> 24 & 0xFF); }