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();
           }
        }
    }
    

      

  • 相关阅读:
    浅谈大学两年
    vue的基本操作
    JS执行环境,作用域链及非块状作用域
    关于AJAX异步请求
    第一个go程序和基本语法
    Golang
    11.二叉树
    10.排序
    9.算法之顺序、二分、hash查找
    高性能异步爬虫
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/8410762.html
Copyright © 2011-2022 走看看