如何实现Android设备之间的TCP通讯?

androidtcp通讯是一种在android设备上实现网络通信的编程方法,主要用于数据传输。

Android TCP通讯

如何实现Android设备之间的TCP通讯?

在移动应用开发中,网络通讯是一项基本且重要的功能,Android平台提供了多种方式来实现网络通讯,其中传输控制协议(TCP)因其可靠性和面向连接的特性,被广泛应用于需要稳定数据传输的场景,本文将详细介绍如何在Android平台上实现TCP通讯,包括客户端和服务端的实现过程、注意事项以及常见问题的解决方案。

一、TCP通讯基础简介

1. 关于IP

IP地址:TCP通讯时,客户端Socket在与服务端建立连接时需要知道服务器的IP地址,这里设置的是服务端IP,而不是客户端设备的IP。

2. 关于端口

端口范围:端口号的范围是0-65535,一般选择较大的数值以避免端口使用冲突。

常用端口:一些常用的端口如80(HTTP)、443(HTTPS)等已被广泛使用,自定义应用应避免使用这些端口。

二、TCP客户端的封装类TcpClient简介

为了让TCP客户端Socket连接在Android上使用更加方便,我们封装了一个工具类——TcpClient,下面是TcpClient的几个主要方法:

如何实现Android设备之间的TCP通讯?

设置连接超时时间public TcpClient setConnectTimeOut(int timeOut)

设置建立连接的参数public TcpClient setSocket(String ip, int port)

发送消息public void sendMessage(String message, String charsetName)

接收消息public String receiveMessage(String charsetName)

关闭连接public void close()

其在Android中的使用流程大致如下:

// 声明
private TcpClient mTcpClient;
// 初始化并设置连接参数
mTcpClient = new TcpClient();
mTcpClient.setConnectTimeOut(5000).setSocket("192.168.50.152", 12345);
// 点击按钮时发送消息并接收返回数据
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn1: //测试
            test();
            break;
        default:
            break;
    }
}
private void test() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            String message = "我是客户端a";
            message = SocketHelper.getMessageByReadLine(message);
            mTcpClient.sendMessage(message, SocketConfig.UTF_8);
            String result = mTcpClient.receiveMessage(SocketConfig.UTF_8);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    LogUtil.i("========我来了=====");
                    mTextView.setText(result);
                }
            });
            LogUtil.i("=====客户端收到结果===result=" + result);
        }
    }).start();
}

三、TcpClient在MainActivity中的使用

下面贴出TcpClient在MainActivity中使用代码:

如何实现Android设备之间的TCP通讯?

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final int PERMISSION_CODE = 1234;
    private TextView mTextView;
    private Button mButton1;
    private TcpClient mTcpClient;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化控件
        initView();
        // 设置监听
        setListener();
        // 申请权限
        requestPermission();
    }
    private void initView() {
        mTextView = findViewById(R.id.tv_show);
        mButton1 = findViewById(R.id.btn1);
    }
    private void setListener() {
        mButton1.setOnClickListener(this);
    }
    private void requestPermission() {
        // Android 6.0及以上版本需要动态申请权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET}, PERMISSION_CODE);
        } else {
            initData();
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, int[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_CODE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            initData();
        } else {
            Toast.makeText(this, "请授予网络权限", Toast.LENGTH_SHORT).show();
        }
    }
    private void initData() {
        // 初始化TcpClient并设置连接参数
        mTcpClient = new TcpClient();
        mTcpClient.setConnectTimeOut(5000).setSocket("192.168.50.152", 12345);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1: //测试
                test();
                break;
            default:
                break;
        }
    }
    private void test() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String message = "我是客户端a";
                message = SocketHelper.getMessageByReadLine(message);
                mTcpClient.sendMessage(message, SocketConfig.UTF_8);
                String result = mTcpClient.receiveMessage(SocketConfig.UTF_8);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        LogUtil.i("========我来了=====");
                        mTextView.setText(result);
                    }
                });
                LogUtil.i("=====客户端收到结果===result=" + result);
            }
        }).start();
    }
}

四、TcpClient源码解析

为了更好地理解TcpClient的工作原理,下面对其源码进行解析:

public class TcpClient {
    private Socket socket;
    private PrintWriter printWriter;
    private BufferedReader bufferedReader;
    private int connectTimeOut;
    private String ip;
    private int port;
    private boolean isClose = false;
    public TcpClient setConnectTimeOut(int timeOut) {
        this.connectTimeOut = timeOut;
        return this;
    }
    public TcpClient setSocket(String ip, int port) {
        this.ip = ip;
        this.port = port;
        return this;
    }
    public void connect() throws IOException {
        if (isClose) return;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InetSocketAddress address = new InetSocketAddress(ip, port);
                    socket = new Socket();
                    socket.connect(address, connectTimeOut);
                    isClose = false;
                    printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                    bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                } catch (IOException e) {
                    e.printStackTrace();
                    isClose = true;
                    if (socket != null) {
                        try {
                            socket.close();
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
    public void sendMessage(String message, String charsetName) {
        if (isClose) return;
        try {
            printWriter.println(message);
            printWriter.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public String receiveMessage(String charsetName) {
        if (isClose) return null;
        try {
            return bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    public void close() {
        if (!isClose) {
            isClose = true;
            try {
                if (printWriter != null) {
                    printWriter.close();
                }
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

五、Tcp通讯客户端使用注意事项及问题排查参考

1. 通讯权限

在Android项目中使用网络功能需要在AndroidManifest.xml文件中添加以下权限:

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

对于Android 6.0及以上版本,还需要动态申请权限:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET}, PERMISSION_CODE);
} else {
    initData();
}

2. 问题排查参考:无法连接到服务器?确保以下几点: IP地址和端口号正确 防火墙设置允许相应端口通过 服务器正在运行并监听指定端口 检查日志输出,确认错误信息

原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1260304.html

本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。

(0)
未希的头像未希新媒体运营
上一篇 2024-11-02 08:07
下一篇 2024-05-09 05:38

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

产品购买 QQ咨询 微信咨询 SEO优化
分享本页
返回顶部
云产品限时秒杀。精选云产品高防服务器,20M大带宽限量抢购 >>点击进入