Android Studio TCP客户端实现

最近在做一个机器人的项目,需要用到TCP通讯这个东西。需要在手机做一个客户端,然后上去网上查了巨久巨多代码,为了避免让有需要的人少走弯路,就做一篇博文来推一下自己的做法,如果各位大大们有什么好的建议,也希望各位可以在评论区写下高见抑或是邮箱到1262706641@qq.com。
由于个人的时间问题,目前这个工程的mian文件加已经上传到github上进行管理,各位大佬可以自取。
传送门:https://github.com/KinFaiLeong/Android-TCP

首先是布局文件的代码:

<?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连接

最后希望大家一起加油!用心攻破每个难题!
在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页
评论 76

打赏作者

Biscuitkids

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值