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

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

页面布局
9414344-6ed559bcad6dbfe2.png
socket编程1png
服务端显示效果

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

9414344-b01888635a810feb.png
socket编程2.png

9414344-5a881770630b1d9c.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-152--安卓网络编程之http协议简介+小案例引入
2.更多关于我
笔名QQ微信爱好
张风捷特烈1981462002zdl1994328语言
我的github我的简书我的CSDN个人网站
3.声明

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值