欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Studio TCP客户端实现

程序员文章站 2022-06-21 20:38:48
最近在做一个机器人的项目,需要用到TCP通讯这个东西。需要在手机做一个客户端,然后上去网上查了巨久巨多代码,为了避免让有需要的人少走弯路,就做一篇博文来推一下自己的做法,如果各位大大们有什么好的建议,也希望各位可以在评论区写下高见抑或是发送到邮箱1262706641@qq.com。首先是布局文件的代码:

最近在做一个机器人的项目,需要用到TCP通讯这个东西。需要在手机做一个客户端,然后上去网上查了巨久巨多代码,为了避免让有需要的人少走弯路,就做一篇博文来推一下自己的做法,如果各位大大们有什么好的建议,也希望各位可以在评论区写下高见抑或是邮箱到1262706641@qq.com。

首先是布局文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true">
        <EditText
            android:id="@+id/ip"
            android:layout_width="280dp"
            android:layout_height="50dp"
            android:background="#7CB342"
            android:hint="IP:"
            android:textColor="#ffffff"
        />
        <EditText
            android:id="@+id/port"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:hint="端口:"
            android:background="#C0CA33"
            android:layout_toRightOf="@id/ip"
            android:inputType="number"
            />
        <Button
            android:id="@+id/connect"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/port"
            android:text="连接服务器"/>

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        <TextView
            android:id="@+id/receive"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:background="#00ACC1"
            android:textColor="#FFFFFF"
            android:hint="接收区"
            android:textSize="18sp"
            android:gravity="center_horizontal"
            />
        <EditText
            android:id="@+id/send"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:background="#3949AB"
            android:hint="发送:"
            android:textColor="#ffffff"
            android:layout_below="@id/receive"/>
        <Button
            android:id="@+id/btn_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="发送"
            android:layout_below="@+id/send"
            />
    </RelativeLayout>
</RelativeLayout>

为了更方便以后的维护和迭代,我将发送模块、连接接收模块放在了不同的线程之中。
接下来先来看看最简单的 发送线程 代码。

    //线程名:Send
    public class Send extends Thread {
    private String send;
    private OutputStream outputStream;
    private  InputStream inputStream;
    private String ip;
    private int port;


    public Send(String msg,int port,String ip) {
        this.send = msg;
        this.ip = ip;
        this.port = port;
    }

    @Override
    public void run() {
        try {
            Socket socket = new Socket(ip,port);
            send="客户端发来:"+send;
            inputStream = socket.getInputStream();
            outputStream = socket.getOutputStream();
            outputStream.write((send+"\n").getBytes("utf-8"));
            outputStream.flush();
            Log.v("AndroidChat","发送成功:"+send);
        }
        catch (Exception e){
            Log.v("AndroidChat","发送失败:"+send+"error"+e.getMessage());
            e.printStackTrace();
        }
    }
	Socket,套接字。利用这个建立和服务器之间的连接,会用就行,想深入了解去看其他大大的详解,这里不做赘述。

(这里插入一些题外话,无论代码有多长,建议各位都应当逐个函数的输入,复制粘贴只会走更多弯路。)

接下来是发送接收线程的代码:

package com.example.tcptext;


import android.util.Log;

import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.net.Socket;

//线程名:ConnectThread
public class ConnectThread extends Thread {
    //Socket msg = null;//定义socket
    private OutputStream out_ip=null;//定义输出流(ip)
    OutputStream outputStream=null;
    private InputStream inputStream;
    private StringBuffer stringBuffer;
    private String ip;
    private int port;
    private Receive receive;
    private String string;
    private boolean isRun = true;
    private  MainActivity.Receive re;

    public ConnectThread(String ip, int port, MainActivity.Receive re) {
        this.ip = ip;
        this.port = port;
        this.re = re;
    }


    @Override
        public void run(){
        Socket so = null;
        try {
            so = new Socket(ip, port);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ": Hello");
            try {
                inputStream = so.getInputStream();
                out_ip = so.getOutputStream();
                Log.v("AndroidChat","开始连接服务器:"+ip+"/"+port);
                sleep(1000);
            }
               catch (IOException | InterruptedException e) {
                Log.v("AndroidChat","连接服务器失败"+e.getMessage());
                e.printStackTrace();
                return;
            }
            Log.v("AndroidChat","成功连接上服务器");
            /*
            下面是接收模块,你可以尝试探究如何将这个模块放在接收线程中。
            */

                try {
                    inputStream = so.getInputStream();
                    final byte[] buffer = new byte[1024];
                    final int len = inputStream.read(buffer);
                    System.out.println(new String(buffer,0,len));
                    Log.v("AndroidChat","接收成功:"+new String(buffer,0,len));
                    string = new String(buffer,0,len);
                    re.setString(string);
                    //上下两行会和MainActivity关联,是回调在显示屏的关键步骤。
                    MainActivity.callback();
                    System.out.println(new String(buffer,0,len));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }

最后是核心模块(MainActivity)

package com.example.tcptext;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {
     private Button mBtn_send;
     private Button mBtn_connect;
     private EditText mEt_send;
     private static TextView mTv_recv;
     private String ip;
     private int port;
     private String msg;
     private ConnectThread ct;
     private Send send;
     private Handler handler;
     static Receive re = new Receive();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTv_recv = findViewById(R.id.receive);
        mBtn_connect = findViewById(R.id.connect);
        mBtn_send = findViewById(R.id.btn_1);


        final EditText mEt_ip = this.findViewById(R.id.ip);
        final EditText mEt_port = this.findViewById(R.id.port);
        final EditText mEt_send = this.findViewById(R.id.send);

/*
设置一个点击事件用以连接线程
*/
        mBtn_connect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ip = mEt_ip.getText().toString();//获取输入的ip
                port = Integer.parseInt(mEt_port.getText().toString());//获取输入的端口号
                ct = new ConnectThread(ip, port, re);//创建一个线程来处理消息的收发
                ct.start();
            }
        });
/*
设计一个点击事件用以发送消息
*/
        mBtn_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                msg = mEt_send.getText().toString();
                send = new Send(msg, port, ip);
                send.start();

            }
        }); 
    }
/*
这里是和连接接收线程中的 re.setString(string) 联动的,自己理解一下怎么走在脑子里面走一次就差不多了。
*/
static class Receive{
        private  String string;
        public String getString(){
            return string;
        }
        public void setString(String s){
            this.string = s;
        }
}
/*
下面的callback和连接接收线程中的 MainActivity.callback() 关联,线程运行到那一步后结束回到MainActivity中。
*/
public static void callback(){
        System.out.println("连接线程执行结束");
        mTv_recv.setText(re.getString());//这里是将接收到的文字显示在接收框内。
}
}
注意:
	1.这里的点击按钮必须要输入好IP和端口号否则会闪退,我也不知道是什么原因,有哪位大大知道的,麻烦说一下。
	2.每次连接接收完信息后都要点击一次连接服务器或者发送一条消息。各位可以一起探讨一下如何重新开启线程,反正我又百年不用Java,这个问题就留给各位了,哈哈哈。

最后,我分享一下我做这个程序的具体思路。零基础的朋友可以参照一下思路来遨游博海:
1.找到两个标准的TCP应用。这很关键,你必须得有标准的应用来测试才知道这是好的还是坏的。
2.善于利用 System.out.println(“哔哩吧啦”); 这个东西能很好的帮助你检查代码运行到什么地方。
3.将整个应用开发分成三个模块:连接服务器模块,发送信息模块,接收信息模块。每个模块还能再细分步骤:1.固定信息的传递(如连接模块就是固定IP和端口号);2.随机信息的传递。
4.优化你的界面,优化代码,做成自己理想的样子。

PS:1.我这里的函数回调是参照网上的一些博文做出的这里放一下链接:

https://blog.csdn.net/weixin_43475124/article/details/83930436?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159499807219195265934921%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159499807219195265934921&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v3~pc_rank_v3-2-83930436.pc_ecpm_v3_pc_rank_v3&utm_term=Java+%E5%88%A9%E7%94%A8%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E7%BA%BF%E7%A8%8B%E6%95%B0%E6%8D%AE%E4%BC%A0%E9%80%92

2.之后我会创一个Github账号将源码放出来,以便和大家一起学习交流。

3.这里用到的两个标准软件:PC端:TCPCOM android端:TCP连接

最后希望大家一起加油!用心攻破每个难题!
Android Studio TCP客户端实现

本文地址:https://blog.csdn.net/weixin_48848716/article/details/107429683