赞
踩
Socket是Java网络编程的基础
了解Socket通信,在java和android开发中都有用处
那么现在就来大概说下
如何搭建服务端和客户端
从而实现Socket通信的
首先我们从java方面开始讲起
服务端代码具体如下:
/** * Created by THINK on 2018/6/4. * 服务端 */ public class SocketService { public static void main(String[] args) { try { //设置服务端端口号 ServerSocket server = new ServerSocket(10086); System.out.println("服务器已经准备就绪"); Socket socket = server.accept();//堵塞方法,等待客户端接入 System.out.println("有一个客户已经连接"); new SocketThread(socket).start();//开启接收内容的线程 Scanner scanner = new Scanner(System.in);//键盘输入类 while (true) { //给客户发一条消息 OutputStream out = socket.getOutputStream(); String str = scanner.next(); out.write(str.getBytes()); //接受客户端发来的消息 // InputStream in = socket.getInputStream(); // byte[] bytes = new byte[1024]; // int count = in.read(bytes); // System.out.println("收到的字节数" + count); // System.out.println("接受到客户消息:" + new String(bytes).trim()); } } catch (IOException e) { e.printStackTrace(); } } }
这里需要注意几点
1) 每个ip地址对应一个端口号,确保连接的唯一性
2) 接受和发送都采用输入输出流的形式,所以要先了解java中I/O流的知识
3) 接受消息我单独封装成了一个线程,这样收发消息的操作各自独立。代码如下
/** * Created by THINK on 2018/6/4. * 服务端接收消息的线程 */ public class SocketThread extends Thread { private Socket socket; private InputStream in; public SocketThread(Socket socket) { try { in = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { while (true) { byte[] bs = new byte[1024]; try { int count = in.read(bs); System.out.println("获取用户输入的内容" + new String(bs, 0, count)); } catch (IOException e) { e.printStackTrace(); } } } }
下面是客户端的配置了
主要需要的是ip地址和端口号
端口号需要双方协商
确保唯一性就好
/** * Created by THINK on 2018/6/4. * 客户端 */ public class Client { public static void main(String[] args) { //创建客户端的Socket对象 try { Socket socket = new Socket("127.0.0.1", 10086); System.out.println("连接服务器"); new ClientThread(socket).start(); Scanner scanner = new Scanner(System.in); while (true) { // InputStream in = socket.getInputStream(); // byte[] bs = new byte[1024]; // in.read(bs);//堵塞方法 等待消息进来 // System.out.println("main: 接受到服务器的消息:" + new String(bs).trim()); //发送消息给服务端 OutputStream out = socket.getOutputStream(); String str = scanner.next(); out.write(str.getBytes()); } } catch (IOException e) { e.printStackTrace(); } } }
这里需要注意:
1)这里的ip地址填写的是本机地址,你们可以根据需求设置不同的ip地址
2)客户端接受消息仍然是新建了一个独立线程,代码如下
/** * Created by THINK on 2018/6/4. * 客户端接收消息的线程 */ public class ClientThread extends Thread { private Socket socket; private InputStream in; public ClientThread(Socket socket) { try { in = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { while (true) { byte[] bs = new byte[1024]; try { int count = in.read(bs); System.out.println("获取服务器输入的内容" + new String(bs, 0, count)); } catch (IOException e) { e.printStackTrace(); } } } }
以上就是java代码来实现Socket通信的简单实例了
下面开始在安卓端实现这个Socket通信
这里采用的是开启服务(Service)的方式
首先需要相关权限
<!--允许应用程序改变网络状态--> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!--允许应用程序改变WIFI连接状态--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!--允许应用程序访问有关的网络信息--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!--允许应用程序访问WIFI网卡的网络信息--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!--允许应用程序完全使用网络--> <uses-permission android:name="android.permission.INTERNET" />
然后记得注册Service,并且在你需要通信的地方开启Service
<!--注册服务--> <service android:name="com.socket.demo.ziliao.SocketService" />
这里我选择在主界面放置一个按钮,用来发送广播给Service
通知Service发送消息给Socket服务端
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //启动核心服务 Intent intent = new Intent(this, com.socket.demo.ziliao.SocketService.class); startService(intent); findViewById(R.id.sockettxt).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent("socket"); intent.putExtra("socketString", "发送消息给Socket服务端"); sendBroadcast(intent); } }); } }
最后是Service页面源代码
public class SocketService extends Service { /** * 主机IP地址 */ public static String HOST = "127.0.0.1"; /** * 端口号 */ public static final int PORT = 6666; private Socket socket;//socket连接 //接收主界面广播 private BroadcastReceiver broadcastReceiver; @Override public void onCreate() { super.onCreate(); broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case "socket"://收到广播 String socketString = intent.getStringExtra("socketString"); new SendMsgThread(socketString).start();//开启发送消息线程 break; } } }; IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("socket");//添加过滤器 registerReceiver(broadcastReceiver, intentFilter);//广播注册 } @Override public int onStartCommand(Intent intent, int flags, int startId) { new InitSocketThread().start(); return super.onStartCommand(intent, flags, startId); } /** * 开启线程连接服务器 */ public class InitSocketThread extends Thread { @Override public void run() { try { socket = new Socket(HOST, PORT); socket.setKeepAlive(true);// Log.d("print", "socketIP:" + HOST); if (socket.isConnected()) {//判断是否连接成功 if (!socket.isClosed() && !socket.isOutputShutdown()) { OutputStream os = socket.getOutputStream(); os.write("我是熊叶平,这是我这边发过来的消息".getBytes()); os.flush(); } new ReadThread(socket).start();//开启接受线程 } else { Log.d("print", "socket断开了"); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 开启线程给Socket服务端发送消息 */ public class SendMsgThread extends Thread { private String str_socket; public SendMsgThread(String str_socket) { this.str_socket = str_socket; } @Override public void run() { try { if (socket.isConnected()) {//判断是否连接成功 if (!socket.isClosed() && !socket.isOutputShutdown()) { OutputStream os = socket.getOutputStream(); os.write(str_socket.getBytes()); os.flush(); } } else { Log.d("print", "socket断开了"); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 开启线程接收Socket服务端消息 */ public class ReadThread extends Thread { private Socket rSocket; public ReadThread(Socket socket) { rSocket = socket; } @SuppressLint("NewApi") @Override public void run() { super.run(); if (null != rSocket && !rSocket.isClosed() && !rSocket.isInputShutdown()) { InputStreamReader isr = null;//获取socket获取到的输入流,并设置编码格式 try { isr = new InputStreamReader(rSocket.getInputStream(), "UTF-8"); char[] by = new char[1024]; //一次读1024个字节 while (isr != null) { int read = isr.read(by);//服务器数据未发过来时,堵塞在这里等待 Message msg = handler.obtainMessage(); msg.what = 1;//只能放数字 /**这里注意:因为读的是1024个字节,但是有可能服务器发送的没有1024个,这样你读到不够的时候系统默认就会打上空格,空格在Log就会是乱码,解决办法就是利用string的构造传入一个输入流,从0开始读取,读完结束,即可去掉所有空格*/ msg.obj = new String(by, 0, read);//用来放对象 handler.sendMessage(msg);// 结果返回给UI处理 } } catch (Exception e) { Log.e("print", "socket连接失败"); try { Thread.sleep(1000);// 延时 Log.e("print", "socket连接失败"); //连接出错时再次调用这个方法,实现重连 new InitSocketThread().start(); } catch (Exception io) { } } } } } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: /**socket就是服务端发送的数据*/ final String socket = msg.obj.toString(); Log.d("print", "handleMessage: " + socket); } } }; @Override public void onDestroy() { super.onDestroy(); if (broadcastReceiver != null) { //取消广播注册 unregisterReceiver(broadcastReceiver); } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
以上就是Android端Socket通信的简单实现
其实在实际开发中
Socket通信可能会遇到不同的开发需求
但是只要掌握了这种通信方式
根据不同的需求去做相应的代码结构设计
熟能生巧
还是没有太大的问题的。
最后祝大家工作愉快,天天进步!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。