Android【Socket通讯】

安卓Socket通信实例

1、Socket通信必须知道的地方

  1. 首先,Socket通信采用TCP模式,客户端需要连接到服务端
  2. 采用网络,需要打开Internet权限
  3. 需要合理调用线程,熟悉线程与输入输出流的使用
  4. socket服务端和客户端编码方式不一致将有可出现中文乱码问题
  5. 在收发数据前,必须和对方建立可靠的连接。
    1. 一个TCP连接必须要经过三次“对话”才能建立,其中的过程非常复杂,
    2. 过程:主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;
    3. 主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;
    4. 主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。

2、文件输入流与输出流的讲解 :

​ 🙂

​ 不管你从磁盘读,从网络读,或者从键盘读,读到内存,就是InputStream。

​ 不管你写到磁盘,写到网络,或者写到屏幕,都是OuputStream。

​ 🍎

我们所说的流,都是针对内存说的,比如为什么打印到屏幕上就是System.out.println();而从屏幕等待用户输入的却是System.in呢?因为对于内存来说,把字符串打印到屏幕上是从内存流向屏幕这个显示器的,也就是输出,而从屏幕等待用户输入呢?就是等待键盘将字符输入到内存中。

所以,你根本就不用死记硬背,当你遇到IO的时候,就想两件事,第一,我的内存是中心,第二看看流的方向(矢量)!

那我访问网络,看网页是什么呢 网络--------------->内存 是 in 因为我们访问页面是要抓取该页面得一个html文件,那我要是在网络上输入帐号密码登陆呢? 是不是内存的东西要写到该服务器上呢,所以当然是out了!

同样socket编程用到更多的IO,这里分别用Server(服务器端)和Client(客户端)来说明

Server: 遇到请求,网络----->内存 IN 服务器应答, 内存------->网络 OUT
-----------------------------------------------------------------
Client: 请求服务, 内存----->网络 OUT 服务器应答, 网络------->内存 IN

3、分步解析(根据实际调用顺序)

Manifest联网请求:

<uses-permission android:name="android.permission.INTERNET"/>

1、初始化Socket

初始化Socket时需要在一个Runnable中创建

Runnable runnable=new Runnable() {
        @Override
        public void run() {
            try {
                Socket socket1=new Socket("192.168.123.101",5000);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };

2、运行Runnable对象

new Thread(runnable).start();

这时候已经初始化完毕,运行成功了

3、读取

此方法需配合线程使用,否则只会读取一次,建议创建一个新的线程继承类

InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[512];
inputStream.read(buffer);
str = new String(buffer,"UTF-8").trim();

4、读取完毕后将str传送给Message

Message自我介绍:Handler接收与处理的消息对象

Message message = Message.obtain();
message.obj=str;
handler.sendMessage(message);

5、显示(Handler+handleMessage内处理传入的消息)

Handler自我介绍:作用就是发送与处理信息

​ 如果希望我正常工作,在当前线程中要有一个Looper对象

super.handleMessage(msg);
//(Textview对象).append("\n\n接收到的信息:"+(msg.obj).toString());
System.out.println((msg.obj).toString());

//提示
/*
Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            
        }
    };
*/

6、发送

//初始化byte数组用于存放准备发送的信息
byte [] sendBuffer = "发送了一条信息".getBytes("UTF-8");
//获得socket的文件输出流
OutputStream outputStream = socket.getOutputStream();
//将sendBuffer写入输出流中,用于输出
outputStream.write(sendBuffer);
//发送成功!

7、最后一句,有话要说

所述的发送与连接一样,都需要线程支持,

所述的三个方法:连接,接收,发送都需要相关的Thread支持,

例如Recieve采用的是线程继承类,

而Send与Connect将都用于new Thread().start的启动

以上将为Socket实例,但不仅仅是最佳实例,可做参考,有更好的请自行更改

//最后,send的调用方法为
new Thread(Send).start();

4、具体实例

消息过长怎么办?

消息过长时考虑在xml的(消息框:Textview)中加入scrollbars

<TextView
...
	android:scrollbars="vertical"/>

MainActivity中设置MovemenrMethod:

(Textview对象).setMovementMethod(ScrollingMovementMethod.getInstance());

Manifest联网请求:

<uses-permission android:name="android.permission.INTERNET"/>

连接:

Runnable Connect=new Runnable() {

        @Override
        public void run() {
            Socket socket = new Socket(serverIP,serverPort);
            Boolean isConnect=true;
            Boolean isReceive=true;
            Receive receive = new Receive(socket);
            receive.start();
            System.out.println("----connected success----");
        }
    };

Handler:

Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            chatItem.append("\n\n接收到的信息:"+(msg.obj).toString());
            System.out.println((msg.obj).toString());
        }
    };

构建接收函数(Receive):

private class Receive extends Thread{//继承线程类
	private InputStream inputStream=null;
    Receive(Socket socket){
        //初始化输入流
        inputStream = socket.getInputStream();
    }
    @Override
    public void run() {
        while (isReceive){
            byte[] buffer = new byte[512];
            inputStream.read(buffer);
           	String str = new String(buffer,"UTF-8").trim();
            Message message = Message.obtain();
            message.obj=str;
            handler.sendMessage(message);
        }
    }
}

构建发送函数(Send):

Runnable Send=new Runnable() {
        @Override
        public void run() {
            byte [] sendBuffer=null;
            
            //可替代为接收输入框的字符串.getBytes
            sendBuffer="发送了一条信息".getBytes("UTF-8");
            
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(sendBuffer);
        }
    };

开始方法:

//连接方法
new Thread(Connect).start();
//发送方法
		//btn.setOnClickListener:new Thread(Send).start();
new Thread(Send).start();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃橘子的季节呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值