美文网首页
IPC之Socket

IPC之Socket

作者: 钦_79f7 | 来源:发表于2019-12-17 12:45 被阅读0次

参考Android开发艺术探索

Socket

Socket:套接字,网络通信值的概念,分为流式套接字和用户数据套接字两种。

  • TCP

    流式套接字, 面向连接的协议,提供稳定的双向通信功能,TCP的连接的建立要通过“三次握手”才能完成,为了提供稳定的数据传输功能,其本身也提供了超时重传的机制,因此具有很高的稳定性。

  • UDP

    UDP是无连接的,提供不稳定的单向通信功能,但让UDP也可以实现双向通信功能。在性能上,UDP具有更好的效率,其缺点是不能保证数据一定能够正确传输,尤其是网络拥塞的情况下。

代码实现

权限

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

服务端

class TCPServerService : Service() {

    private var mIsServiceDestroyed = false

    private val mDefinedMessages = arrayOf("你好啊,洒洒水所", "今天上海听爱情", "我屮艸芔茻", "你这人真尼玛操蛋", "j今Tina踩了一坨屎")

    private val mTCPServerThread = Thread(Runnable {
        //监听本地8688 端口
        val serverSocket = ServerSocket(8688)
        //循环接收客户端的连接请求,用来支持多个客户端连接
        while (!mIsServiceDestroyed) {
            val client = serverSocket.accept()
            println("accept")
            //每接收到一个客户端的连接请求之后,开启一个线程用来处理客户端的消息
            Thread(Runnable { responseClient(client) }).start()
        }
    })

    override fun onCreate() {
        super.onCreate()
        mTCPServerThread.start()
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onDestroy() {
        mIsServiceDestroyed = true
        super.onDestroy()
    }

    /**
     * 接收客户端的消息,并向客户端灰回复消息
     */
    private fun responseClient(client: Socket) {
        val reader = BufferedReader(InputStreamReader(client.getInputStream()))
        val writer = PrintWriter(BufferedWriter(OutputStreamWriter(client.getOutputStream())), true)
        writer.println("欢迎来到聊天室!")
        //循环接收当前线程对应的客户端发来消息,并回复
        while (!mIsServiceDestroyed) {
            val str: String? = reader.readLine()
            println("msg from client : $str")
            if (str == null) {
                break
            }
            val i = Random().nextInt(mDefinedMessages.size)
            writer.println(mDefinedMessages[i])
            println(mDefinedMessages[i])
        }
        //循环结束后,关闭操作
        println("client quit.")
        reader.close()
        writer.close()
        client.close()
    }
}

客户端

class TCPClientActivity : AppCompatActivity() {
    companion object {
        private const val MSG_RECEIVE_NEW_MSG = 1
        private const val MSG_SOCKET_CONNECTED = 2
    }

    private var mClientSocket: Socket? = null
    private var mPrintWriter: PrintWriter? = null

    @SuppressLint("SetTextI18n")
    private val mHandler = Handler(Handler.Callback {
        when (it.what) {
            MSG_RECEIVE_NEW_MSG -> tvMsgContainer.text = tvMsgContainer.text.toString() + it.obj
            MSG_SOCKET_CONNECTED -> btnSend.isEnabled = true
        }
        true
    })

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_tcpclient)

        btnSend.setOnClickListener { clickBtnSend() }

        startService(Intent(act, TCPServerService::class.java))

        Thread(Runnable { connectTCPServer() }).start()
//        btnSend.postDelayed({  }, 3000)//延迟连接,等待服务端启动完成
    }

    private fun connectTCPServer() {

        var socket: Socket? = null
        while (socket == null) {
            //通过循环来处理服务端启动延迟的问题,当然这里的循环也是基于处理失败重连的机制上的
            //如果不做try catch 处理,当连接失败时会抛错
            try {
                socket = Socket("localhost", 8688)
                mClientSocket = socket
                mPrintWriter = PrintWriter(BufferedWriter(OutputStreamWriter(socket.getOutputStream())), true)
                mHandler.sendEmptyMessage(MSG_SOCKET_CONNECTED)
                println("connect server success")
            } catch (e: Exception) {
                SystemClock.sleep(1000)
                println("connect server failed, retry...")
            }
        }

        val br = BufferedReader(InputStreamReader(socket.getInputStream()))
        while (!isFinishing) {
            var msg: String? = null
            try {
                msg = br.readLine()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            if (msg != null) {
                val time = formatDateTime(System.currentTimeMillis())
                val showedMsg = "server $time: $msg\n"
                mHandler.obtainMessage(MSG_RECEIVE_NEW_MSG, showedMsg).sendToTarget()
            }
        }

        println("quit...")
        mPrintWriter?.close()
        br.close()
        socket.close()
    }

    private fun formatDateTime(time: Long): String {
        return SimpleDateFormat("(HH:mm:ss)", Locale.CHINA).format(Date(time))
    }

    @SuppressLint("SetTextI18n")
    private fun clickBtnSend() {
        val msg: String? = inputMsg.text.toString()
        if (!msg.isNullOrEmpty()) {
            mPrintWriter?.println(msg)
            inputMsg.setText("")
            val time = formatDateTime(System.currentTimeMillis())
            val showedMsg = "self $time : $msg\n"
            tvMsgContainer.text = tvMsgContainer.text.toString() + showedMsg
        }
    }

    override fun onDestroy() {
        mClientSocket?.shutdownInput()
        mClientSocket?.close()
        mHandler.removeCallbacksAndMessages(null)        
        super.onDestroy()
    }
}

AndroidManifest

        <service
            android:name=".demo.socket.TCPServerService"
            android:process=":tcp_server" />

        <activity
            android:name=".demo.socket.TCPClientActivity"
            android:windowSoftInputMode="adjustResize" />

相关文章

  • IPC之Socket

    参考Android开发艺术探索 Socket Socket:套接字,网络通信值的概念,分为流式套接字和用户数据套接...

  • 【计算机网络】Socket

    Socket 介绍 概述 socket是一种IPC方法,它允许位于同一主机或使用网络连接起来的不同主机的应用程序之...

  • Android面试及其汇总操作一

    Android面试及其汇总操作一 对IPC的看法 IPC进程通信的方式有哪些? Linux中有socket,nam...

  • 春招笔记

    Linux支持的IPC:管道,消息队列,共享内存,信号量,Socket。只有Socket支持CS模式,其他的也可以...

  • 网络编程:Socket API

    Socket API 1.OS IPC机制 OS提供的IPC机制一般分为两类: 本地IPC只允许位于同一计算机上的...

  • Python Socket 编程概览

    简评:socket 和 socket API 用于通过网络发送消息,它们提供了一种进程间通信(IPC)方式。网络可...

  • Binder AIDL proxy stub

    Binder与AIDL?Android中有多种IPC机制,如AIDL,Messenger,Socket,Conte...

  • 操作系统知识点

    操作系统 IPC 共享内存 管道 socket RPC romote procesure calls 同步机制 ...

  • Unix domain socket

    一、 概述UNIX Domain Socket是在socket架构上发展起来的用于同一台主机的进程间通讯(IPC)...

  • Nginx中fastcgi_pass配置概述

    一、Socket概述 Socket通信是大家耳熟能详的一种进程间通信方式(IPC Inter-Process Co...

网友评论

      本文标题:IPC之Socket

      本文链接:https://www.haomeiwen.com/subject/qwssnctx.html