Socket的具体使用

Socket的具体使用

TCP:

首先服务端创建一个ServerSocket,并绑定目标端口,然后循环调用accept方法,这个方法用于监听客户端的连接,它是阻塞的,当收到连接后继续执行,这时创建一个新的线程,用于为这个客户端提供服务,然后重新循环刚才的流程。
客户端创建一个Socket,并设置ip或目标主机地址和端口号。然后使用这个socket获取输出流,将要发送的数据写入输出流,最后使用socket执行shutdownOutput关闭输出流,这时数据就发送出去了。如果是接收数据,那么需要获取输入流,并读取输入流的数据。完成操作后需要close关闭流,否则会导致资源浪费和异常。

具体代码:

Server

//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口  
val serverSocket = ServerSocket(8888)  
var socket: Socket?  
//记录客户端的数量  
var count = 0  
println("***服务器即将启动,等待客户端的连接***")  
//循环监听等待客户端的连接  
while (true) {  
    //调用accept()方法开始监听,等待客户端的连接  
    socket = serverSocket.accept()  
    //创建一个新的线程  
    val serverThread = ServerThread(socket)  
    //启动线程  
    serverThread.start()  
    count++ //统计客户端的数量  
    KLog.d(msg = "客户端的数量:$count")  
    val address: InetAddress = socket.inetAddress  
    KLog.d(msg = "当前客户端的IP:" + address.hostAddress)  
}

Client

//1.创建客户端Socket,指定服务器地址和端口  
val socket = Socket("localhost", 8888)  
//2.获取输出流,向服务器端发送信息  
val os: OutputStream = socket.getOutputStream() //字节输出流  
val pw = PrintWriter(os) //将输出流包装为打印流  
pw.write("用户名:whf;密码:789")  
pw.flush()  
socket.shutdownOutput() //关闭输出流  
//3.获取输入流,并读取服务器端的响应信息  
val inputStream: InputStream = socket.getInputStream()  
val br = BufferedReader(InputStreamReader(inputStream))  
var info: String?  
while (br.readLine().also { info = it } != null) {  
    KLog.d(msg = "我是客户端,服务器说:$info")  
}  
//4.关闭资源  
br.close()  
inputStream.close()  
pw.close()  
os.close()  
socket.close()

UDP:

首先创建一个DatagramSocket,并绑定目标端口,然后创建一个字节数组用于读取接收的数据,调用receive接收客户端的数据,这个方法是阻塞的。它还有另一个方法send,用于发送数据。
客户端创建一个 DatagramSocket,然后设置服务器主机地址和端口号。然后将需要发送的数据包装成数据包DatagramPacket对象,通过send发送。

具体代码

Server

// 创建接收端  
val ds = DatagramSocket(12345)  
/**  
 * 接收数据包  
 * receive(DatagramPacket p)  
 * 从这个套接字接收数据报包。  
 */
val data = ByteArray(1024)  
val dp = DatagramPacket(data, data.size)  
ds.receive(dp)  
// 获取接受到的信息  
val str = String(data, 0, dp.length)  
println(str)  
// 关闭接收端  
ds.close()

Client

/**  
 * 准备发送端  
 * DatagramSocket()  
 * 构造一个数据报套接字绑定到本地主机机器上的任何可用的端口。  
 */
val ds = DatagramSocket()  
/**  
 * 准备数据包  
 * 1、 DatagramPacket(byte[] buf, int length)     
 * 构造一个 DatagramPacket length接收数据包的长度  
 * 2、 String的getBytes()  
 * 方法是得到一个操作系统默认的编码格式的字节数组  
 * 3、 setSocketAddress()     
 * 设置SocketAddress(通常是IP地址+端口号)都的远程主机发送数据报。  
 * 4、InetSocketAddress(InetAddress addr, int port)  
 * 创建一个套接字地址的IP地址和端口号。  
 */
val str = "你好,UDP"  
val ch = str.toByteArray()  
val dp = DatagramPacket(ch, ch.size)  
dp.socketAddress = InetSocketAddress("127.0.0.1", 12345)  
// 发送数据  
ds.send(dp)  
// 关闭套接字  
ds.close()

ServerThread

private class ServerThread(socket: Socket?) : Thread() {
    // 和本线程相关的Socket
    private var socket: Socket? = null
    //线程执行的操作,响应客户端的请求
    override fun run() {
        var inputStream: InputStream? = null
        var isr: InputStreamReader? = null
        var br: BufferedReader? = null
        var os: OutputStream? = null
        var pw: PrintWriter? = null
        try {
            //获取输入流,并读取客户端信息
            inputStream = socket!!.getInputStream()
            isr = InputStreamReader(inputStream!!)
            br = BufferedReader(isr)
            var info: String?
            while (br.readLine().also { info = it } != null) { //循环读取客户端的信息
                KLog.d(msg = "我是服务器,客户端说:$info")
            }
            socket!!.shutdownInput() //关闭输入流
            //获取输出流,响应客户端的请求
            os = socket!!.getOutputStream()
            pw = PrintWriter(os)
            pw.write("欢迎您!")
            pw.flush() //调用flush()方法将缓冲输出
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            //关闭资源
            try {
                pw?.close()
                os?.close()
                br?.close()
                isr?.close()
                inputStream?.close()
                if (socket != null) socket!!.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
    init {
        this.socket = socket
    }
}
posted @ 2023-06-14 13:16  Ysun_top  阅读(181)  评论(0编辑  收藏  举报