Android 中的Socket通信

       公司新项目中涉及到Socket通信有关的东西,虽然之前接触到一点,不过好长时间不用基本上忘个七七八八了,网上查了查资料,根据项目中的需求自己做了个小Demo,欢迎大家指正.

1.需求:

      1.1:客户端测量完毕后,将测量数据以Socket的方式上传的服务端;

      1.2:客户端每过1秒中向服务端发送一次心跳,服务端记录心跳时间并且每两秒钟判断一次心跳间隔,如果上一次心跳时间与现在时间间隔超过两秒钟视为连接异常,否则为连接正常.

2.基本概念

       2.1:TCP IP协议:在早期计算机网络中,各大厂商都有着自己的一套网络协议,互不兼容,这就导致说中文的只能跟说中文的交流而不能跟说英文的交流,这样的现象很不友好,为了让不同种类的所有计算机都能毫无障碍的交流,就必须要使用一套统一的标准,所以internet应运而生,在Internet的各种协议中,最重要的两个协议就是TCP和IP协议.

        2.2:在数以万计的计算机中,如果你想和某台计算机A通信,那么就必须知道A这台计算机在互联网中的ip地址(ip地址是每个计算机在网络中的唯一标识),而ip协议就是负责把你要发送的数据分割成n段打包然后从你的计算机发送到A计算机,但是在运输的过程中ip协议不会保证能把数据完整的送到A计算机,当然也不能保证数据会按照切割的先后顺序到达A计算机.

        2.3:TCP协议是建立在IP协议之上的协议,TCP协议会在两台计算机之间建立可靠的连接,并且会保证ip协议切割打包的ip包完整顺序的到达A计算机,即使在传输的过程中丢包了,TCP协议也会重新发送ip包,保证数据的完整性.TCP协议会把传输的数据流分成适当长度的报文段,一个单独的报文段除了包含要传输的数据流外还包含源计算机ip地址、端口和目标计算机ip地址、端口.

        2.4:端口:在给A计算机发消息的时候,只知道A的IP地址是不够的,还需要知道给A计算机的哪个程序发消息,例如我是给A计算机的微信发送的数据,那么我就需要知道微信这个网络程序向计算机申请的端口号,这样两个计算机中的两个网络程序才能互相建立连接.

    2.5:TCP/IP的四层协议: 

        2.5.1网络接口层(数据链路层)是物理传输通道,对于网络层下发的ip数据包通过网络选择合适的路径转发;对于从网络上接收到的物理帧,抽出ip数据包并交给网络层.

        2.5.2网络层对于网络接口层上传的ip数据包进行数据检验,检验此数据是否到达目的地址,是则去除包头将剩余数据上传到传输层,否则选择合适的路径继续转发;对于传输层下发的分组数据添加包头,封装成ip数据包交给网络接口层.

         ARP:address resolution protocol  地址解析协议,通过获取到的ip地址来寻找获取相应主机的MAC地址;

        RARP: reverse address resolution protocol 反地址解析协议,通过已知的MAC地址来获取相应主机的ip地址;

        ICMP:Internet control manage protocol 网络控制管理协议,是网络层的补充,用于实现报文回送功能,像PING命令就是一种ICMP协议,用于发送ICMP的echo包,用于检验网络是否通畅。

        2.5.3传输层实现两台主机的应用程序之间的端到端的通信,传输层可以格式化信息流、提供可靠传输(为实现可靠传输,传输层协议规定接收端必须发回确认,假如分组丢失,必须重新发送).

        2.5.4应用层是应用程序间沟通的层,这里对用户来说是一个个的图形化界面,如浏览器 QQ  微信等,为发起网络请求、接收网络传输提供具体的应用程序.

3.Socket

       3.1 Socket(套接字)对TCP/IP协议进行封装,是一个供我们编程调用的接口,它属于传输层,所以Socket分为流套接字(streamsocket,基于TCP协议)和数据报套接字(datagramsocket,基于UDP协议),

        TCP协议:提供的是面向连接、可靠的字节流服务,客户端和服务器进行数据交互前双方必须建立连接,之后才能传输数据,TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

        UDP协议:是一个简单的面向数据报的运输层协议,他只是负责把应用程序传给ip层的数据报发出去(不会像TCP那样拆分),但是不能保证他们能到达目的地,由于UDP在传输数据的时候不用建立连接、没有超时重发等机制,故UDP的传输速度很快.

        3.2 Socket使用(基于TCP)

<!-- 允许应用程序改变网络状态 -->
<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" />

//客户端

Socket mSocket = new Socket("192.168.55.13", 20000);
mSocket.setSoTimeout(10000);//设置连接超时时间
mSocket.setTcpNoDelay(true);//设置立即发送
DataOutputStream dataOutputStream = new DataOutputStream(mSocket.getOutputStream());//获取输出流
DataInputStream dataInputStream = new DataInputStream(mSocket.getInputStream());//获取输入流

//读取服务端发送过来的消息

class SocketThrad extends Thread {
        @Override
        public void run() {
            while (true) {
                if (dataInputStream != null) {
                    try {
                        final String msg = dataInputStream.readUTF();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                mText.setText(msg);
                            }
                        });
                    } catch (IOException e) {
                        try {
                            dataOutputStream.close();
                            dataInputStream.close();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                        e.printStackTrace();
                    }
                }
            }
        }
    }

//给服务端发送消息

@Override
public void onClick(View v) {
            if (dataOutputStream != null) {
                try {
                    dataOutputStream.writeUTF("消息");
                    dataOutputStream.flush();
                } catch (IOException e) {
                    try {
                        dataOutputStream.close();
                        dataInputStream.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    e.printStackTrace();
                }
            }

//服务端代码
class SocketThread extends Thread {
    @Override
    public void run() {
        try {
            mServerSocket = new ServerSocket(20000);
            while (true) {
                Log.d("TAG", "等待SOCKET连接");
                mSocket = mServerSocket.accept();
                dataOutputStream = new DataOutputStream(mSocket.getOutputStream());
                dataInputStream = new DataInputStream(mSocket.getInputStream());
                Log.d("TAG", "SOCKET连接");
                readMsg(dataInputStream);
            }
        } catch (IOException e) {
            try {
                dataOutputStream.close();
                dataInputStream.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }
}
private void readMsg(DataInputStream dataInputStream) {
    while (true) {
        if (dataInputStream != null) {
            try {
                Log.d("TAG", "等待数据发送");
                final String msg = dataInputStream.readUTF();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.d("TAG", "有数据发送");
                        mText.setText(msg);
                    }
                });
            } catch (IOException e) {
                try {
                    dataOutputStream.close();
                    dataInputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
        }
    }
}

//给客户端发送消息

@Override
public void onClick(View v) {
    if (dataOutputStream != null) {
        try {
            dataOutputStream.writeUTF("消息");
            dataOutputStream.flush();
        } catch (IOException e1) {
            try {
                dataOutputStream.close();
                dataInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            e1.printStackTrace();
        }
    }
}

目前只是实现了两个单机之间的相互简单通信,贴上了部分代码以供大家参考,有什么建议欢迎指出;

猜你喜欢

转载自blog.csdn.net/zhao_Android/article/details/82768926