zoukankan      html  css  js  c++  java
  • 1 TCP/IP通信

    重点参考长链接http://blog.csdn.net/fengyuzhengfan/article/details/38830115

    http://blog.csdn.net/Jsagacity/article/details/78531819#

    http://www.runoob.com/w3cnote/android-tutorial-socket1.html

    1 电脑(或ESP8266)连接WIFI,建立服务 192.168.3.8  8080

    1.1 查看电脑地址

    1.2 电脑建立服务 192.168.3.8  8080

    2 手机连接WIFI,创建客户申请服务 

    手机在wifi 下分配的地址是 192.168.3.9 

    2.1 手机打开软件

    点击发送

    电脑接收

    2手机端工程

     手机端分为两个工程

    1短链接。发送完消息就自动断开。不牵扯链接中断问题,但无法接收消息。

    2长连接。发送完消息还可以接收消息。实现数据互传,但是还没有加入重链接功能。

    2.1 AsyncTask建立的短链接

    1 布局管理

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.dongdong.myapplication.MainActivity">
    
    
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/LinearLayout1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical"
            tools:context=".MainActivity"
            android:weightSum="1">
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="center"
                android:weightSum="1">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="IP:"
                    android:layout_weight="0.04" />
                <EditText
                    android:id="@+id/SIP"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="0.65" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="端口:"/>
                <EditText
                    android:id="@+id/IPort"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="0.17" />
    
            </LinearLayout>
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="left"
            android:weightSum="1">
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="连接"/>
    
            <Button
                android:id="@+id/bt_send"
                android:layout_width="88dp"
                android:layout_height="wrap_content"
                android:text="发送"
                android:layout_below="@+id/tv_content"
                android:layout_alignParentStart="true"
                tools:layout_editor_absoluteY="0dp"
                tools:layout_editor_absoluteX="8dp" />
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="清空"/>
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:gravity="left"
            android:weightSum="1">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="发送区:"
                android:layout_weight="0.04" />
    
            <EditText
                android:id="@+id/sentText"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
    
            <TextView
                android:id="@+id/tv_send_text"
                android:layout_width="241dp"
                android:layout_height="43dp"
    
                android:text="发送的内容"
                android:layout_below="@+id/bt_send"
                tools:layout_editor_absoluteX="8dp"
                tools:layout_editor_absoluteY="8dp"
    
                android:layout_weight="0.03" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:gravity="left"
            android:weightSum="1"
            android:layout_weight="0.12">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="接收区:"
                />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="清空"/>
            <TextView
                android:id="@+id/tv_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
    
                android:gravity="left"
                android:text="接收的内容"
                android:layout_alignParentTop="true"
                android:layout_alignParentStart="true"
                tools:layout_editor_absoluteY="0dp"
                tools:layout_editor_absoluteX="8dp" />
        </LinearLayout>
        </LinearLayout>
    
    </android.support.constraint.ConstraintLayout>
    

      

      

      2 添加网络权限

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

      

      3 工程目录

    1采用AsyncTask 异步模式

     输入参数问题

    2.1  函数输入参数1可以设置输入参数,可以是控件

      SendAsyncTask myTask = new SendAsyncTask(SIP_target,IPort__target);     

    2.2 

       myTask.execute(str);

    对应这个参数是

    doInBackground(String... params) 

      

    package com.example.dongdong.myapplication;
    
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    
    import android.view.View;
    import android.view.View.OnClickListener;
    
    import android.widget.TextView;
    import android.widget.EditText;
    import android.widget.Button;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity implements OnClickListener {
    
      //  1.1 定义
        private Button bt_send;
        private TextView tv_content;
        private TextView tv_send_text;
    
        private EditText SIP;
        private EditText IPort;
        private EditText sentText;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
             // 1.2 控件初始化
            InitView();
            //  2 开启服务器
            MobileServer mobileServer = new MobileServer();
            mobileServer.setHandler(handler);
            new Thread(mobileServer).start();
    
        }
    
        private void InitView() {
            tv_content = (TextView) findViewById(R.id.tv_content);
            tv_send_text = (TextView) findViewById(R.id.tv_send_text);
    
            sentText=(EditText) findViewById(R.id.sentText);
            SIP=(EditText) findViewById(R.id.SIP);
            IPort=(EditText) findViewById(R.id.IPort);
    
            bt_send = (Button) findViewById(R.id.bt_send);
            bt_send.setOnClickListener(this);
    
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.bt_send:
                   // String str = "Sent to the ESP8266";
                    String str="请输入命令";
                    int IPort__target=8080;
                    String  SIP_target="192.168.1.1";
                   if( sentText!=null)
                   {
                       str=sentText.getText().toString().trim();
                   }
                    if (SIP!= null) {
                        SIP_target=SIP.getText().toString().trim();
    
                    }
                    if (IPort!= null) {
                        String msg = IPort.getText().toString().trim();
                        if (msg != null && msg.length() > 0) {
                            IPort__target = Integer.parseInt(msg);
                        }
                    }
                    // 链接IP
                    SendAsyncTask myTask = new SendAsyncTask(SIP_target,IPort__target);
                    //SendAsyncTask myTask = new SendAsyncTask();
                    // 初始发送的消息
                    myTask.execute(str);
    
                    tv_send_text.setText(str);
                    break;
            }
    
        }
    
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        tv_content.setText("WiFi模块发送的:" + msg.obj);
                        Toast.makeText(MainActivity.this, "接收到信息", Toast.LENGTH_LONG)
                                .show();
                }
            }
        };
    }
    

      

      

      

    package com.example.dongdong.myapplication;
    
    import java.io.IOException;
    
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import java.io.DataInputStream;
    
    import android.os.Handler;
    import android.os.Message;
    
    public class MobileServer implements Runnable {
        private ServerSocket server;
        private DataInputStream in;
        private byte[] receice;
    
        private Handler handler = new Handler();
    
        public MobileServer() {
        }
    
        public void setHandler(Handler handler) {
            this.handler = handler;
        }
    
        @Override
        public void run() {
    
            try {
                //5000是手机端开启的服务器的端口号,ESP8266进行TCP连接时使用的端口,而IP也是通过指令查询的联入设备的IP
                server = new ServerSocket(5000);
                while (true) {
                    Socket client = server.accept();
                    in = new DataInputStream(client.getInputStream());
                    receice = new byte[50];
                    in.read(receice);
                    in.close();
    
                    Message message = new Message();
                    message.what = 1;
                    message.obj = new String(receice);
                    handler.sendMessage(message);
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

      

    package com.example.dongdong.myapplication;
    
    import java.io.IOException;
    import java.io.PrintStream;
    import java.net.Socket;
    import android.os.AsyncTask;
    
    
    
    public class SendAsyncTask extends AsyncTask<String, Void, Void> {
       // public class SendAsyncTask extends AsyncTask<String, Void, Void> {
    
        //这里是连接ESP8266的IP和端口号,IP是通过指令在单片机开发板查询到,而端口号可以自行设置,也可以使用默认的,333就是默认的
        private  static String IP ;
        private  static int PORT ;
    
        private Socket client = null;
        private PrintStream out = null;
    
       public SendAsyncTask(String ip,int port)
       {
          super();
           this.IP = ip;
           this.PORT = port;    }
    
        @Override
        protected Void doInBackground(String... params) {
            String str = params[0];
            try {
                client = new Socket(IP, PORT);
                client.setSoTimeout(5000);
                // 获取Socket的输出流,用来发送数据到服务端
                out = new PrintStream(client.getOutputStream());
                out.print(str);
                out.flush();
    
                if (client == null) {
                    return null;
                } else {
                    out.close();
                    client.close();
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    }
    

    2 Handler 建立的长连接

    功能描述

    1. 建立长链接,链接按钮建立链接 ,发射按钮发射信号,停止按钮结束。也可以改成短链接,生成类的时候把信号加进去。
    2. 界面和通信线程各自有访问彼此的Handler,从而实现数据线程互传互传。
    3. 主界面之外,建立通信线程发送消息。通信线程里又新建一个线程,用于专门接收服务器的数据。

    现有问题

    1. 若连超时异常处理
    2. 若连接上但之后中断,连接重检测问题。

    工程代码

    如果自己新建工程要加入这些代码,注意修改工程名字。一般每个文件的第一行,只一句根据实际建立的工程确定。

     2.1 网路权限

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

     添加后完成整的代码

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.espressif.myapplication">
        <uses-permission android:name="android.permission.INTERNET"/>  
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    

      

     

    2 布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       >
    
    
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/LinearLayout1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical"
            tools:context=".MainActivity"
            android:weightSum="1">
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="center"
                android:weightSum="1">
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="IP:"
                    android:layout_weight="0.04" />
                <EditText
                    android:id="@+id/SIP"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="0.65"
                    android:text="192.168.1.102"
                    />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="端口:"/>
                <EditText
                    android:id="@+id/IPort"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="0.17"
                    android:text="8080"
                    />
    
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="left"
                android:weightSum="1">
                <Button
                    android:id="@+id/bt_connect"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="连接"/>
    
                <Button
                    android:id="@+id/bt_send"
                    android:layout_width="88dp"
                    android:layout_height="wrap_content"
                    android:text="发送"
                    android:layout_below="@+id/tv_content"
                    android:layout_alignParentStart="true"
                    tools:layout_editor_absoluteY="0dp"
                    tools:layout_editor_absoluteX="8dp" />
    
                <Button
                    android:id="@+id/bt_stop"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text=""/>
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="left"
                android:weightSum="1">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="发送区:"
                    android:layout_weight="0.04" />
    
                <EditText
                    android:id="@+id/sentText"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content" />
    
                <TextView
                    android:id="@+id/tv_send_text"
                    android:layout_width="241dp"
                    android:layout_height="43dp"
    
                    android:text="发送的内容"
                    android:layout_below="@+id/bt_send"
                    tools:layout_editor_absoluteX="8dp"
                    tools:layout_editor_absoluteY="8dp"
    
                    android:layout_weight="0.03" />
            </LinearLayout>
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="left"
                android:weightSum="1"
                android:layout_weight="0.12">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="接收区:"
                    />
                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="清空"/>
                <TextView
                    android:id="@+id/tv_content"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
    
                    android:gravity="left"
                    android:text="接收的内容"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"
                    tools:layout_editor_absoluteY="0dp"
                    tools:layout_editor_absoluteX="8dp" />
            </LinearLayout>
        </LinearLayout>
    
    </android.support.constraint.ConstraintLayout>
    

     

    3 工程文件 

    package com.espressif.myapplication;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    
    import android.view.View;
    import android.view.View.OnClickListener;
    
    import android.widget.TextView;
    import android.widget.EditText;
    import android.widget.Button;
    import android.widget.Toast;
    
    
    public class MainActivity extends AppCompatActivity  implements OnClickListener  {
        //  1.1 定义
        private Button bt_connect;// 链接
        private Button send;// 发送
        private Button bt_stop; //停止
    
        public TextView tv_content; // 显示接收的命令
        private TextView tv_send_text;  // 显示发送的命令
    
        private EditText SIP; //IP地址
        private EditText IPort; //端口
        private EditText sentText; // 发送内容
        // 1.2 定义与服务器通信的子线程
        boolean isConnect=true;//连接还是断开
        ClientThread clientThread;
        Handler handler;
    
        // 2 主函数
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 2.1 控件初始化
            InitView();
    
    
    
        }
    
    // 1 界面控件初始化
        private void InitView() {
            tv_content = (TextView) findViewById(R.id.tv_content);
            tv_send_text = (TextView) findViewById(R.id.tv_send_text);
    
            sentText=(EditText) findViewById(R.id.sentText);
            SIP=(EditText) findViewById(R.id.SIP);
            IPort=(EditText) findViewById(R.id.IPort);
    
            send = (Button) findViewById(R.id.bt_send);
            send.setOnClickListener(this);
    
            bt_connect=(Button) findViewById(R.id.bt_connect);
            bt_connect.setOnClickListener(this);
            bt_stop = (Button) findViewById(R.id.bt_stop);
            bt_stop.setOnClickListener(this);
    
            // 2.2 用于和主界面通信
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case 0x123:
                            tv_content.setText("WiFi模块发送的:" + msg.obj.toString());
                            //  tv_content.append("
    " + msg.obj.toString());
                            break;
                    }
                }
            };
    
        }
    // 2 链接TCP/IP 链接目标服务
        public void connectIP(){
    
            int IPort__target=8080;
            String  SIP_target="192.168.1.1";
    
    
            if (SIP!= null) {
                SIP_target=SIP.getText().toString().trim();
    
            }
            if (IPort!= null) {
                String msg = IPort.getText().toString().trim();
                if (msg != null && msg.length() > 0) {
                    IPort__target = Integer.parseInt(msg);
                }
            }
    
    
            //  2 开启服务器
            if (isConnect == true) //标志位 = true表示连接
            {
    
                // 链接IP
    
                clientThread = new ClientThread(handler);
                clientThread.setip_port(SIP_target, IPort__target);
                new Thread(clientThread).start();
    
                if(clientThread.isConnect==false){
              //  if(clientThread.s.isConnected()&& !clientThread.s.isClosed()){
                    isConnect = true;//置为true
                    bt_connect.setText("连接");//按钮上显示连接
    
                }
                else{
                    isConnect = false;//置为false
                    bt_connect.setText("断开");//按钮上显示--断开
                }
            }
            else //标志位 = false表示退出连接
            {
                isConnect = true;//置为true
                bt_connect.setText("连接");//按钮上显示连接
                clientThread.stop_connect();
                }
        }
    // 3 发送信息
        public void Sendmsg(){
    
            String msg="1123";
            if( sentText!=null)
            {
                msg=sentText.getText().toString();
            }
            //更新文本框
            tv_send_text.setText(msg);
            // 发送函数
            try {
                Message msga = new Message();
                msga.what = 0x345;
                msga.obj = sentText.getText().toString();
                clientThread.revHandler.sendMessage(msga);
    
            }
            catch (Exception e)
            {
                e.printStackTrace();
                tv_send_text.setText("发送失败!");
            }
    
    
    
        }
    
     // 4 按键点击触发器
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
    
                //1链接函数
                case R.id.bt_connect:
                    connectIP();
                    break;
    
                //2 发送信息
                case R.id.bt_send:
                    Sendmsg();
                    break;
                // 停止
                case R.id.bt_stop:
                 // 停止函数
                    break;
            }
        }
    
        }
    

      

    package com.espressif.myapplication;
    
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.OutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.text.TextUtils;
    
    import java.net.SocketTimeoutException;
    
    public class ClientThread implements Runnable
    {
        private  static  int Port_target;
        private  static  String IP_target;
        boolean isConnect=true;//连接还是断开
        public Socket s;
        // 该线程所处理的Socket所对应的输入流
        BufferedReader br =null;
        // 输出
        OutputStream os =null;
    
        // 定义向UI线程发送消息的Handler对象
        private Handler handler;
        // 定义接收UI线程的消息的Handler对象
        public Handler revHandler;
    
    
    
     // 2.1设置通线程向主界面通信对象
    public ClientThread(Handler handler) {
            this.handler = handler;   // 定义向UI线程发送消息的Handler对象
    }
    
    // 2.2设置链接地址
    public void setip_port(String IP,int port){
           IP_target=IP;
          Port_target=port;
     }
     // 2.3从服务器接收信息线程
    public void connectthread(){
        // 启动一条子线程来读取服务器响应的数据
        new Thread()
        {  String content =null;
            @Override
            public void run()
            {
                // 不断读取Socket输入流中的内容。
                try
                {
                    while ((content = br.readLine())!=null)
                    {
                        // 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据
                        Message msg =new Message();
                        msg.what = 0x123;
                        msg.obj = content;
                        handler.sendMessage(msg);
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }.start();
    
    }
    //  2.4将接收命令更新主界面显示框
        public void fruh_UI(){
    
            // 为当前线程初始化Looper
            Looper.prepare();
            // 创建revHandler对象
            revHandler =new Handler()
            {
                @Override
                public void handleMessage(Message msg)
                {
                    // 接收到UI线程中用户输入的数据
                    if (msg.what == 0x345)
                    {
                        // 将用户在文本框内输入的内容写入网络
                        try
                        {
                            os.write((msg.obj.toString() + "
    ")
                                    .getBytes("utf-8"));
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }
            };
            // 启动Looper
            Looper.loop();
        }
    
     // 2.4终止链接
    public void stop_connect(){
            try
            {
    
                    isConnect = false;
                    s.close();//关闭连接
                    s = null;
    
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    
     public void run()
        {byte[] acceptdata1=null;
            try
            {
                s =new Socket(IP_target, Port_target);
                if(s.isConnected()&& !s.isClosed()){isConnect=true;}
                // 接收数据
                br =new BufferedReader(new InputStreamReader( s.getInputStream()));
                //存放数据
                os =s.getOutputStream();
    
                // 新线程 接收数据
                connectthread();
                // 更新主界面显示框
                fruh_UI();
    
           }
           catch (SocketTimeoutException e1)
           {  isConnect=false;
             System.out.println("网络连接超时!!");
           }
           catch (Exception e)
           {
              e.printStackTrace();
           }
        }
    }
    

      

  • 相关阅读:
    Nginx负载均衡+代理+ssl+压力测试
    Nginx配置文件详解
    HDU ACM 1690 Bus System (SPFA)
    HDU ACM 1224 Free DIY Tour (SPFA)
    HDU ACM 1869 六度分离(Floyd)
    HDU ACM 2066 一个人的旅行
    HDU ACM 3790 最短路径问题
    HDU ACM 1879 继续畅通工程
    HDU ACM 1856 More is better(并查集)
    HDU ACM 1325 / POJ 1308 Is It A Tree?
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/8410762.html
Copyright © 2011-2022 走看看