Android使用Socket通信

    xiaoxiao2022-07-07  227

    在学习Socket之前,我们需要掌握一些知识,如java多线程,Handler等.

    Java多线程

    https://blog.csdn.net/qq_40318498/article/details/84726026

    C#Socket通信

    https://blog.csdn.net/qq_40318498/article/details/90384688

    Android Handler消息处理

    https://blog.csdn.net/qq_40318498/article/details/89897690


    源码已上传到github上

    https://github.com/Githubforusc2018/AndroidSocket


    使用技术

    1.Handler 2.多线程 3.网络编程

    Android登录界面截图

    Android客户端界面截图

    Android服务端界面截图


    Client客户端核心代码

    //连接服务器,返回的是一个Socket对象的连接来保持与服务器的通信. int port = Integer.parseInt(clientPort.getText().toString()); mysocket = new Socket(clientIp.getText().toString(),port); //连成功了,服务器一直显示数据. //一个子线程,循环读取消息. while(true){ InputStream is = mysocket.getInputStream(); //192.168.43.224手机的wifi ip 地址. byte[] buffer = new byte[1024*1024]; int len = is.read(buffer); //获取输入流,读取从服务端发送过来的消息. String result = new String(buffer, 0, len); /* 第一次读到的是Ip地址,必须保存.*/ if (mycount++==1){ myIp = result; //这里是与C#服务端通信的需求,我是检测是否正常连接用的. } Message message = new Message(); message.what = 1; //标识符为1,表明显示在自己的消息框 Bundle bundle = new Bundle(); bundle.putString("msg", result); //将读取到的信息传入handler中处理. message.setData(bundle); handler.sendMessage(message); } //发送消息,这里直接使用mysocket.getOutputStream()也可以. DataOutputStream writer = new DataOutputStream(mysocket.getOutputStream()); writer.write(clientMessage.getText().toString().getBytes()); //发送消息 //发送,我也要写入handler中. Message message = new Message(); message.what = 1; //标识符为1,表明显示在自己的消息框 Bundle bundle = new Bundle(); bundle.putString("msg", myIp+" : "+clientMessage.getText().toString()); //ip + 说明 message.setData(bundle); handler.sendMessage(message); //Handler public Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what==1){ Bundle data = msg.getData(); sb.append(data.getString("msg")); //StringBuffer sb = new StringBuffer();这里直接不用这个也可以. sb.append("\n"); serverMessageText.setText(sb.toString()); } } };

    Server服务端端核心代码

    //设置一个端口,监听客户端的连接,监听手机服务端50000端口. serverSocket = new ServerSocket(50000); //绑定sport clientSocket = serverSocket.accept(); //serverSocket是该服务器的,clientSocket返回客户端的ip和端口. //clientSocket.toString返回的是socket(192.168.1.107 + port) //userText.setText(clientSocket.toString()); 报错???,使用handler处理成功. //读取消息,开启一个子线程,反复监听消息. while(true){ //一开始客户端能给服务端发消息,服务端不能给客户端发消息,幸好解决了 InputStream is = clientSocket.getInputStream(); byte[] buffer = new byte[1024*1024]; int len = is.read(buffer); String result = new String(buffer, 0, len); //读消息跟发送消息与客户端几乎一致. Message message = new Message(); Bundle bundle = new Bundle(); bundle.putString("msg",result); message.setData(bundle); message.what = 1; //标识符为1 handler.sendMessage(message); } //发送消息,也是需要开启一个线程. OutputStream writer = clientSocket.getOutputStream(); writer.write(normalMessage.getText().toString().getBytes()); //发给1看看. String result = "发送成功"; Message message = new Message(); Bundle bundle = new Bundle(); bundle.putString("msg",result); message.setData(bundle); //发送handler,更新ui message.what=1; handler.sendMessage(message); @SuppressLint("HandlerLeak") public Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what==1){ Bundle data = msg.getData(); sb.append(data.getString("msg")); sb.append("\n"); normalText.setText(sb.toString()); } } };

    主界面中的图片切换动作使用handler处理和动画处理. ListView客户端和ListView服务端在以上基础上,使用listview组件来显示消息,这里我对格式弄了一个处理,因此可能无法使用ListView客户端来与c#客户端进行数据交换,而只能使用Android与Android进行通信,可以解决该问题,如下.

    //Server服务端发送消息 String result = userText.getText().toString() + "-" + classText.getText().toString() + "-" + ageText.getText().toString(); //发送的是userText 内容 classText 内容 ageText内容 中间使用 - 来分割,这样容易把一串字节流按指定格式分割成我们想要的部分. writer.write(result.getBytes()); //Client客户端 Text = result.split("-"); //按分开. HashMap<String,Object> map = new HashMap<String, Object>(); map.put("User",Text[0]); map.put("Class",Text[1]); map.put("Age",Text[2]); mylist.add(map); //我们发现,若C#服务端发送过来的消息不包含-因此Text[0] = result,Text[1],Text[2]抛出下标越界异常. //修改. int i=0; for(i=0;i<result.length();i++){ if (result.charAt(i)=='-'){ break; } } if (i==result.length()){ //说明是C#发送过来的,对Text进行处理. Text[0] = result; Text[1] = "null"; Text[2] = "null"; }else{ Text = result.split("-"); //按分开. }

    Java split测试


    一些总结:

    1.服务端(假设是模拟机)可以向手机(服务端)发送请求连接,因此知道手机的ip地址能够正常连接,而手机客户端无法通过电脑的ip地址访问到模拟机(服务端),若要连接,需要知道模拟机的ip地址.

    2.一个Message只能传给一个handler,若要使用handler处理多个任务,需要初始化多个Message.

    3.可以使用bundle向handler中(可以是同一个活动)传递数据,在handler中使用Bundle bundle = msg.getData()来获取数据。

    4.在退出活动的时候,需要关闭I/O流和socket连接.

    5.使用5个write,怎么第一个输出有换行,明明程序中没有换行,最后写成一行可以解决该问题. (若不写成一个write,可以通过trim()方法去掉多余的空格和换行)

    6.Handler是Android提供的一个用来更新UI的机制(Android不允许在子线程更新UI),也是一个消息处理的机制

    7.一些超时的任务处理,如网络下载等需要使用子线程来完成,因此默认情况下,主线程等待5s以上就会关闭该活动。


    功能:

    1.在C#Socket通信的基础上,增加Android Socket通信 2.能够让Android跟C#通信 3.能够让Android与Android进行通信.

    最新回复(0)