3--安卓网络编程之Socket编程

实现场景:手机A作为客户端,手机B作为服务端,通过Socket实现信息交互与处理。 如下图:客户端通过ip和端口连接服务器,客户端发送hello,服务端接收后,处理成大写发送给客户端,通过Toast显示 虽然是个简单的测试,但基本涵盖了Socket编程的所有基础知识

页面布局

socket编程1png

服务端显示效果

打开服务以及有设备加入时,界面上的反应

socket编程2.png

socket编程.png

一、服务端实现

1.服务端界面:TCPServerActivity.java

1.通过ServerSocket开启服务 2.将连接的客户端显示在服务端界面 3.为该客户端开启服务线程

case R.id.id_btn_start_server://开启服务
    new Thread(() -> {
        try {
            //1.开启服务器
            ServerSocket serverSocket = new ServerSocket(8080);
            runOnUiThread(() -> mIdTvLink.setText("服务已开启"));
            mJoinRunnable = new JoinRunnable(serverSocket);
            //2.将连接的客户端显示在服务端界面
            mJoinRunnable.setOnConnListener(ip -> runOnUiThread(() -> {
                mIdTvLink.append("\n" + ip + "已连接");
            }));
            //3.为该客户端开启服务线程
            new Thread(mJoinRunnable).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).start();
    break;
case R.id.id_btn_close_server://关闭服务
    if (mJoinRunnable != null) {
        mIdTvLink.setText("服务未开启");
        mJoinRunnable.close();
    }
    break;
2.JoinRunnable:每次客户端加入时创建的线程

1.通过服务端ServerSocket获取Socket对象 2.获取连接的客户端ip,并设置连接时的回调监听 3.通过Socket获取输入I流,读取客户端的信息 4.通过Socket获取输出O流,向客户端发送信息 5.进行IO流操作

/**
 * 作者:张风捷特烈<br/>
 * 时间:2018/10/14 0014:8:01<br/>
 * 邮箱:1981462002@qq.com<br/>
 * 说明:每次客户端加入时创建的线程
 */
public class JoinRunnable implements Runnable {

    private ServerSocket mServerSocket;//ServerSocket对象
    private Socket mSocket;//Socket对象

    public JoinRunnable(ServerSocket serverSocket) {
        mServerSocket = serverSocket;
    }

    @Override
    public void run() {
        InputStream is = null;
        OutputStream os = null;
        try {
            //1.通过服务端ServerSocket获取Socket对象
            mSocket = mServerSocket.accept();
            //2.获取连接的客户端ip,并设置连接时的回调监听
            String ip = mSocket.getInetAddress().getHostAddress();
            if (mOnConnListener != null) {
                mOnConnListener.conn(ip);
            }
            //3.通过Socket获取输入I流,读取客户端的信息
            is = mSocket.getInputStream();
            //4.通过Socket获取输出O流,向客户端发送信息
            os = mSocket.getOutputStream();
            //5.IO操作
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = is.read(buf)) != -1) {
                String msg = new String(buf, 0, len).toUpperCase();
                //将读出来的信息进行操作后返回给客户端
                os.write(("服务端发来信息:" + msg).getBytes());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭客户端连接
     */
    public void close() {
        try {
            mServerSocket.close();
            mSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //客户端连接时的监听
    public interface OnConnListener {
        void conn(String ip);
    }

    private OnConnListener mOnConnListener;

    public void setOnConnListener(OnConnListener onConnListener) {
        mOnConnListener = onConnListener;
    }
}

二、客户端页:

@OnClick({R.id.id_btn_send, R.id.id_btn_setip})
public void onViewClicked(View view) {
    switch (view.getId()) {
        case R.id.id_btn_setip:
            //通过ip和端口连接服务端
            new Thread(() -> connServer(mIdEtIp.getText().toString(), 8080)).start();
            break;
        case R.id.id_btn_send:
            //将键盘输入内容发送给服务端
            mPwOut.println(mIdTcp.getText());
            break;
    }
}

/**
 * 通过ip和端口连接服务端核心代码
 *
 * @param ip   ip地址
 * @param port 端口
 */
private void connServer(String ip, int port) {
    try {
        //1.创建客户端Socket对象(ip,端口)
        mSocket = new Socket(ip, port);
        //2.通过socket对象获取字节输出流,并包装成PrintWriter----用于发送给服务端数据
        mPwOut = new PrintWriter(mSocket.getOutputStream(), true);
        //3.通过socket对象获取字节输出流
        InputStream is = mSocket.getInputStream();
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = is.read(buf)) != -1) {
            msg = new String(buf, 0, len).toUpperCase();
            runOnUiThread(() -> ToastUtil.showAtOnce(TCPClientActivity.this, msg));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
@Override
protected void onDestroy() {
    super.onDestroy();
    if (mSocket != null) {
        try {
            mSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

后记:捷文规范

1.本文成长记录及勘误表

项目源码

日期

备注

V0.1--无

2018-10-15

2--安卓网络编程之http协议简介+小案例引入

2.更多关于我

笔名

QQ

微信

爱好

张风捷特烈

1981462002

zdl1994328

语言

我的github

我的简书

我的CSDN

个人网站

3.声明

1----本文由张风捷特烈原创,转载请注明 2----欢迎广大编程爱好者共同交流 3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 4----看到这里,我在此感谢你的喜欢与支持

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

[WCF安全系列]谈谈WCF的客户端认证[用户名/密码认证]

对于基于Internet的应用,基于用户名和密码的认证方式是最为常用的,而WCF为你提供了不同模式的用户名认证方式。首先还是从用户凭证的表示说起。 一、用户名/...

23890
来自专栏葡萄城控件技术团队

Winform文件下载之WinINet

在C#中,除了webclient我们还可以使用一组WindowsAPI来完成下载任务。这就是Windows Internet,简称 WinINet。本文通过一个...

24480
来自专栏静晴轩

浅谈android中的目录结构

之前在android游戏开发中就遇到本地数据存储的问题:一般情形之下就将动态数据写入SD中存储,在没有SD卡的手机上就需另作处理了;再有在开发android应用...

361100
来自专栏北京马哥教育

linux服务器下LNMP安装与配置方法

云豆贴心提醒,本文阅读时间6分钟 一、准备 1.准备php函数的rpm包 2.准备lnmp其他的源代码包 3.安装php-5.2.14源代码包所需要的函数支...

41590
来自专栏AndroidTv

讲讲断点续传那点儿事提问理论基础代码示例

这次想来讲讲断点续传,以前没相关需求,所以一直没去接触,近阶段了解了之后,其实并不复杂,那么也便来写一篇记录一下,分享给大伙,也方便自己后续查阅。

12320
来自专栏Danny的专栏

【SSH快速进阶】——探索Hibernate对象的三种状态:Transient、Persistent、Detached

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

12320
来自专栏Java成长之路

jsonp详解

说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义...

30640
来自专栏随心DevOps

[实战篇] Python 运维中使用并发

今天从大哥手里接了一个需求: 验证一下新的 Docker 镜像仓库(Docker Registry)是否迁移成功了 简单粗暴的方法就是拿到老仓库中的镜像列表(I...

461120
来自专栏Young Dreamer

web worker 扫盲篇

什么是woker 官方的解释是这样的: worker是一个对象,通过构造函数Worker创建,参数就是一个js文件的路径;文件中的js代码将运行在主线程之外的w...

38980
来自专栏everhad

App设计:消息推送和界面路由跳转

概要 app消息推送、显示通知栏,点击跳转页面是很一般的功能了,下面以个推为例演示push集成,消息处理模块及app内部路由模块的简单设计。 推送 推送sdk集...

54690

扫码关注云+社区

领取腾讯云代金券