在安卓应用中实现Socket通信:创建服务端和客户端

Android Socket使用详解 即套接字,是一个对 TCP / IP协议进行封装 的编程调用接口(API)即通过Socket,我们才能在Andorid平台上通过TCP/IP协议进行开发Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)成对出现,一对套接字:Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)} 阅读详情

介绍:本文主要介绍在安卓中使用Socket创建服务端和客户端进行通信,服务端可以管理多个客户端连接,完善的异常处理,接口回调,可以满足大部分需求,更多功能自行拓展…

关于Socket套接字:

是网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

使用Socket进行网络通讯的一般步骤如下:

  1. 创建Socket对象,指定服务器的IP地址和端口号。
  2. 使用Socket对象的getInputStream()和getOutputStream()方法获取输入输出流,用于接收和发送数据。
  3. 使用输出流发送请求到服务器,使用输入流读取服务器返回的数据。
  4. 使用完毕后,通过调用Socket对象的close()方法关闭Socket连接。

创建Socket服务端

功能包括启动服务,关闭连接,发送消息,接收消息,管理客户端,将事件回调给外界等

class SocketServer(private val port: Int, private val listener: SocketServerListener? = null) : Thread() {
    private val TAG = "SocketServer"

    private lateinit var serverSocket: ServerSocket // serverSocket 对象
    private val clientHandlers = mutableListOf<ClientHandler>() // 存储每个客户端线程
    private val executor = Executors.newSingleThreadExecutor()
    override fun run() {
        startServer()
    }

    // 启动服务器的方法
    private fun startServer() {
        try {
            serverSocket = ServerSocket(port)
            Log.i(TAG, "Server is running on port $port")

            while (!isInterrupted) {
                val clientSocket = serverSocket.accept() // 接受客户端连接
                listener?.onClientConnected(clientSocket) // 通知客户端已连接
                val clientThread = ClientHandler(clientSocket, listener) // 为每个客户端创建一个新的线程
                clientThread.start()

                clientHandlers.add(clientThread)  // 安全地添加 Handler 到列表
            }
        } catch (e: Exception) {
            listener?.onError(e)
        }

    }

    // 关闭服务器的方法
    fun stopServer() {
        clientHandlers.forEach { it.closeConnection() } // 关闭所有客户端线程

        try {
            serverSocket.close() // 关闭 ServerSocket
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    // 当线程被中断时,关闭服务器
    override fun interrupt() {
        stopServer()
        super.interrupt()
    }

    // 定义处理每个客户端连接的线程
    class ClientHandler(private val socket: Socket, private val listener: SocketServerListener? = null) : Thread() {
        private var printWriter: PrintWriter? = null
        private var bufferedReader: BufferedReader? = null

        fun sendMessage(msg: String) {
            if (printWriter != null) {
                synchronized(printWriter!!) {
                    printWriter?.println(msg)
                }
            }
        }

        override fun run() {
            printWriter = PrintWriter(socket.getOutputStream(), true)
            bufferedReader = BufferedReader(InputStreamReader(socket.getInputStream()))

            try {
                var message: String? = null
                // 服务端接收数据
                while (socket.isConnected && bufferedReader?.readLine()
                        .also { message = it } != null) {
                    // 当接收到消息时,通过 listener 通知外部
                    listener?.onMessageReceived(message!!)
                    // 回应客户端
                    //printWriter?.println("Received: $message")
                }
            } catch (e: IOException) {
                listener?.onError(e)
                e.printStackTrace()
            } finally {
                // 确保最后会关闭连接
                closeConnection()
            }
        }

        // 关闭连接的方法
         fun closeConnection() {
            try {
                socket.close() // 关闭 socket 连接
                printWriter?.close()
                bufferedReader?.close()
            } catch (e: IOException) {
                listener?.onError(e)
            }
            Log.d("ClientHandler", "Client disconnected ${socket.inetAddress.hostAddress}")
            listener?.onClientDisconnected(socket) // 通知外部客户端已断开
        }
    }

    // 发送消息到客户端的方法
    fun sendMessage(message: String) {
        executor.submit {
            clientHandlers.forEach {
                it.sendMessage(message)
            }
        }
    }
}

// 定义一个接口,用于接收消息和通知客户端连接和断开
interface SocketServerListener {
    fun onMessageReceived(message: String)
    fun onClientConnected(client: Socket)
    fun onClientDisconnected(client: Socket)

    fun onError(e: Exception)
}

创建Socket客户端

功能包括建立连接,关闭连接,发送消息,接收消息,异常处理,将事件回调给外界等

class SocketClient(
    private val serverAddress: String,
    private val serverPort: Int,
    private val listener: SocketClientListener?
) {
    private var socket: Socket? = null
    private var out: PrintWriter? = null
    private var reader: BufferedReader? = null
    private val executor = Executors.newSingleThreadExecutor()
    private val connectLatch = CountDownLatch(1)

    fun connect() {
        executor.execute {
            try {
                socket = Socket(serverAddress, serverPort)
                out = PrintWriter(socket!!.getOutputStream(), true)
                reader = BufferedReader(InputStreamReader(socket!!.getInputStream()))
                listener?.onConnected()

                connectLatch.countDown() // 通知已经连接
            } catch (e: IOException) {
                listener?.onConnectionFailed(e)
            }
        }
    }

    fun sendMessage(message: String) {
        executor.execute {
            connectLatch.await() // 等待连接完成
            out?.println(message)
        }
    }

    fun receiveMessages() {
        executor.execute {
            try {
                connectLatch.await() // 等待连接完成
                var message: String? = null
                while (reader?.readLine().also { message = it } != null) {
                    listener?.onMessageReceived(message!!)
                }
            } catch (e: IOException) {
                listener?.onError(e)
            }
        }
    }

    fun close() {
        executor.execute {
            try {
                // socket 和 reader 关闭顺序不能变,否则会阻塞在 reader?.close()
                socket?.close()
                reader?.close()
                out?.close()
                listener?.onDisconnected()
            } catch (e: IOException) {
                listener?.onError(e)
            }
        }

    }
}

interface SocketClientListener {
    fun onConnected()
    fun onMessageReceived(message: String)
    fun onConnectionFailed(e: Exception)
    fun onDisconnected()
    fun onError(e: Exception)
}

获取IP地址

public static String getIPAddress() {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
                for (InetAddress addr : addrs) {
                    if (!addr.isLoopbackAddress() && addr instanceof Inet4Address) {
                        return addr.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            Log.e("getIPAddress", e.toString());
        }
        return "";
    }

如何使用

服务端:

 val listener = object : SocketServerListener {
            override fun onMessageReceived(message: String) {
                XLog.i(" SocketServerListener  Message received from client: $message")
            }

            override fun onClientConnected(client: Socket) {
                XLog.i(" SocketServerListener  Client connected: ${client.inetAddress.hostAddress}")
            }

            override fun onClientDisconnected(client: Socket) {
                XLog.i(" SocketServerListener  disconnected: ${client.inetAddress.hostAddress}")
            }

            override fun onError(e: Exception) {
                XLog.i(" SocketServerListener  onError: ${e.message}")
            }
        }
        server = SocketServer(12345, listener)
        server.start()

客户端:

 val client = SocketClient(getIPAddress(), 12345, object : SocketClientListener {
                override fun onConnected() {
                    XLog.i(" SocketClientListener  onConnected")
                }

                override fun onMessageReceived(message: String) {
                    XLog.i(" SocketClientListener  onMessageReceived: $message")
                }

                override fun onConnectionFailed(e: Exception) {
                    XLog.i(" SocketClientListener  onConnectionFailed: ${e.message}")
                }

                override fun onDisconnected() {
                    XLog.i(" SocketClientListener  onDisconnected")
                }

                override fun onError(e: Exception) {
                    XLog.i(" SocketClientListener  onError")
                }

            })
            client.connect()
            client.sendMessage("Hello, server!")

            client.sendMessage("啊哈哈哈 鸡汤来喽!!!")
            client.receiveMessages()

最后

此片文章用来记录学习,方便大家拿来即用,知识点不多,注释已经尽可能详细了,收工,下班!

Android 客户端Socket 与 Java服务端ServerSocket 小编精心为大家准备了一手资料以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术【附】架构书籍BAT面试的20道高频数据库问题解析Java面试宝典Netty实战算法BATJ面试要点及Java架构师进阶资料加入社区:https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0。 阅读详情

相关推荐

Android与服务器端通信方式之Socket详解

通过Socket通信,Android客户端可以与服务器端进行实时数据传输,实现实时交互和数据监控等功能。在实际开发中,可以根据具体的需求进行扩展和优化。需要注意的是,在使用Socket进行通信时,服务器端和客户端的IP地址和端口号必须一致。Socket是一种提供网络通信功能的编程接口,它可以在不同设备之间建立连接并进行数据的发送和接收。在Android中,可以使用Java的Socket类来实现与服务器端的通信。下面是一个简单的示例,演示了Android客户端与服务器端通过Socket进行通信的过程。

IunScala的博客 334

Android Socket 简单介绍

本文简单介绍了Android 中Socket 的使用方法,并通过简单的示例帮助理解。

我怀里的猫的博客 3780

安卓与PC间Socket通信详细教程及源码解析

Socket即套接字,是网络编程的基础接口,它存在于计算机网络中的两个程序间,用于处理数据包的发送与接收。Socket提供了多种网络通信协议的支持,如TCP和UDP,它们分别用于保证数据传输的可靠性和速度。安卓设备通过网络与外界进行通信是实现丰富功能应用的基础。Socket通信作为一种网络通信技术,能够让安卓应用在不同的网络协议(如TCP/IP、UDP等)下交换数据。无论是在数据同步、远程服务访问,还是在物联网等需要远程设备间互动的场景中,Socket通信都扮演着重要的角色。

weixin_33239721的博客 1083

【小沐学Android】Android实现socket网络通信

🍺SOCKET网络通信系列文章链接如下:🍺 🎈【小沐学python】(一)Python简介和安装🎈 🎈Python实现socket网络通信🎈 🎈C++实现socket网络通信(Windows)🎈 🎈Android实现socket网络通信🎈 🎈nodejs实现socket网络通信🎈 Android实现socket网络通信1、简介1.1 socket流程1.2 需要在子线程运行1.3 需要的权限2、环境配置2.1 Android Studio下载2.2 真机无线调试3、TCP方式3.1 服务端3.2 客户端3

爱看书的小沐 1万+

导带、价带

价带是电子的“束缚态”能量区间,决定材料的化学性质;导带是电子的“自由态”能量区间,直接决定材料的导电能力;禁带宽度则是区分金属、半导体与绝缘体的核心参数。通过调控能带结构(如掺杂、应变工程),可设计出具有特定电学和光学特性的功能材料,推动电子信息、能源转换等领域的技术革新。

weixin_51552564的博客 5116

TwinCAT3 Modbus-TCP Client/Server使用

/起始地址是12289//起始地址是12294。

panjinliang066333的博客 7732

安卓Socket通讯简单示例

安卓Socket通信详解 1>Socket是什么:      也叫做“套接字”用于描述IP地址和端口,在网络上的主机一般运行多个软件,提供多种服务,每种服务都会打开一个Socket,并绑定到一个端口上,不同端口对应不同服务        网络上的两个程序通过双向的通讯连接实现数据交换,,这个双向链路的一端称为一个Socket,Socket通常用于实现客户端和服务端的连接,Socket是TCP

Allan的博客 3144

26版SPSS操作教程(高级教程第十章)

#大道之行,在于坚持 #本期内容:二分类Logistic回归模型 #由于导师最近布置了学习SPSS这款软件的任务,因此想来平台和大家一起交流下学习经验,这期推送内容接上一次高级教程第九章的学习笔记,希望能得到一些指正和帮助~

你好! 1598

socket客户端与服务端正常通信,服务端过了一段时间就接收不到客户端的数据了

https://blog.youkuaiyun.com/persistencegoing/article/details/84376427 All rights reserved.No part of this article may be reproduced or distributed by any means,or stored in a database or retrieval system,...

persistence勿忘初心 6050

智能车图像处理22-进阶篇14--小s的判断

这篇文章中主要讲述智能车图像处理中 : 小s的判断方法。

taiyuezyh的博客 2566

【AI编程】Claude Code 最强AI 编程利器项目实战详解

Claude Code 最强AI 编程利器项目实战详解

congge 7396

安卓应用开发Socket通信 客户端+服务器端

这个项目是基本的Socket网络通信,适合小白,大神瞅瞅就好,有好的建议希望大家多多讨论

m0_55809179的博客 1237

手把手教你用Pytorch代码实现Transformer模型(超详细的代码解读)

本文整理了非常清楚的Transformer模型结构图,建议大家在看代码的时候能结合这个结构图来理解,这样理解起来会比较容易! 用Pytorch实现Transformer的完整代码

捡起一束光的博客 7万+

Android -- Socket通信

1、通信简介 安卓与服务端的通信方式主要有两种,一种是 Http 通信,一种是 Socket 通信。 Socket 属于传输层,因为 TCP/IP 协议属于传输层,解决的是数据如何在网络中传输的问题 Http 协议属于应用层,解决的是如何包装数据 两者最大的差异,就是工作方式的不同: Http:采用 请求—响应 方式 1、即建立网络连接后,当 客户端 向 服务器 发送请求后,服务端才能向...

一只驴在敲代码 1132

Airtest进阶使用篇-提高脚本稳定性+批量运行脚本

Airtest进阶篇,主要分享如何提高脚本稳定性+如何批量运行脚本生成测试报告!

程序员小杨哥的博客 2569

标题:Stata17安装后遇到Java安装问题解决方法

设置JAVA_HOME环境变量:在Windows上,您需要设置JAVA_HOME环境变量以告诉Stata Java的安装路径。d. 输入变量名为JAVA_HOME,变量值为Java安装路径。注意:请确保您的Java版本与Stata兼容,并使用正确的Java安装路径。设置Stata的Java安装路径:现在,您需要告诉Stata Java的安装路径。如果您看到Java版本信息,则表示Java已成功安装。如果没有安装,请先下载并安装Java。确认Java已安装:首先,请确保您的计算机上已经正确安装了Java。

CyberSparkZ的博客 2867

Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)

ZERO、前言 有关通信原理内容是在网上或百科整理得到,代码部分为本人所写,如果不当,还望指教。 一、Socket通信简介  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双

其实并不难,是你太悲观 17万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

安卓的Socket客户端开发及应用

一、应用场景 在做嵌入式开发中,比如我们通过开发板控制电机从而驱动小车前进和转向,希望能通过手机安卓app控制小车。这时我们可以引入安卓的Socket编程。 实现思路:假设小车前进和转向的消息获取是经过串口通信完成的,要实现安卓app的控制,可以先在开发板上开启socket服务端,当在安卓app界面上点击按钮时,按钮实现客户端的创建并与服务端建立连接,客户端对服务端发送消息。这时,服务端接收消息后,剩下的步骤便可由串口通信完成。 二、界面简单布局代码 activity_main.xml: <Relat

Heavysea的博客 1046

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

android如何与服务器,安卓如何与服务器通信 Android服务器通信

Android服务器通信的几种方式详解大 学学习网络基础的时候老师讲过,网络由下往上分为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。通过初步的了解,小编知道IP协议对应于网 络层,TCP协议对应于传输层,而HTTP协议对应于应用层,三者从本质上来说没有可比性。Android客户端怎么与服务器数据库连接?不能与数据库连接的 Android客户端不能直接与服务器数据库连接。数据库是需要...

weixin_34849898的博客 1920

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

安卓Socket与pc端c#服务器的通信 附完整代码

一、前言 小生不才,学习安卓socke通信打了很多滚,遇到过很多问题,也翻过前辈们关于socket的讲解,很杂各有见解,案例也不是很完整,于是特地将此安卓Socket与pc端c#服务器的通信代码讲解与socket的资料整理一遍加深理解,希望能有所帮助,小生没写过几次博客,欢迎各位大佬提出宝贵意见。安卓客户端项目源代码与pc端C#服务器与客户端的资源已经上传:安卓Socket与pc端c#服务器的通...

最数据的专栏 976

Android网络编程(使用socket进行通信)

Java提供了ServerSocket,事实上当你创建该类的对象并提供一个端口资源你就建立了一个固定位置可以让计算机来访问。端口的分配必须是唯一的,它是唯一标识每台计算机每一个服务的。端口号必须是从0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的。网络编程的基本模型就是c/s模型,简单的理解是两个进程之间相互通讯,其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置,并去建立两者之间的联系,然后完成数据的通讯就可以了。

2401_85112783的博客 1231

安卓使用完整底层linux,Android使用socket使底层和framework通信

一般的native和framework的通信是通过jni,但是这一般只是framework调用native,native如果有消息要怎样通知上层呢?Android中GSP模块提供一种解决思路,但是实现有些复杂,这里介绍一种使用socket通信的方法可以使native和framework自由通信,具体实现如下:android中使用jni对linux中的socket进行了封装。使用起来十分的方便。由于...

weixin_34901693的博客 317

安卓应用安装过程学习

声明:此文章来自的学习记录。

qq_63217130的博客 1138

Socket编程在安卓开发中的应用

Socket作为一种网络编程的接口,俗称“套接字”,通常用于描述IP地址和端口号,是一种用于通信的句柄。应用程序通常通过套接字向网络发出请求或响应网络请求。在安卓开发中,用于实现客户端与服务器之间的通信除了针对HTTP进行网络通信的方法之外,另外一种就是Socket网络编程了。 Socket通信一般可以分为两种:一种是基于TCP协议的可靠传输,另一种是基于UDP协议的不可靠传输。下面,我就以TCP

Daisy_ruo的博客 1537

安卓socket聊天

安卓基于Socket通信(服务器配合) 1.话不多说进入正题,先创建服务端,在Android Studio中创建Java代码,如下图所示: 选择Java Library 需要改名字的自己随意 2.创建Client Manager客户端管理类来管理客户端的消息,因为省时间就直接从我上篇博客的代码基础上进行的修改~代码如下所示:(自己编写代码块提交后总有乱码...所以只能把自己的代...

weixin_30413739的博客 81

【转】 基于Socket通信的聊天室

原文地址:http://blog.youkuaiyun.com/xiaoxujie2007_/article/details/7720265 服务器端 ChatServer.java import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.ne...

iteye_14430的博客 194
上一篇: 把握人工智能的浪潮:普通人如何利用AI走向成功?
下一篇: 一个用Kotlin编写简易的串行任务调度器
_蓝橙
博客等级 码龄7年 1179粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值