(1) 概念
socket用来实现服务端和客户端的网络通信,在Java中,用ServerSocket作为服务端,socket作为客户端。
(2) 原理
ServerSocket在指定的端口监听客户端发来的请求,通过Accept()方法收到请求的话就加入请求队列中,否则就一直处于阻塞状态,直到客户端发来请求,服务端通常在主线程里接收请求,收到请求后把socket交给子线程处理,在子线程中对客户端做出响应。socket通常由一个IP地址(或者主机域名)和一个端口号确定,IP地址用于确定主机地址,端口号用于确定服务端程序运行在哪个端口上,在创建socket的时候也可以指定客户机的Ip和端口。
(3) 使用
客户端发出请求并且服务端接收之后,客户端的socket通过getOutStream()获取输出流,通过输出流向服务端写数据,服务端通过socket的getInputStream()获取输入流,通过输入流可以得到客户端发来的数据。同样的,服务端也可以向输出流中写入数据,客户端通过输入流获取服务端的响应数据。并且Socket在读数据的时候是阻塞式的,如果没有读到数据程序会一直阻塞,不会接收新的请求,所以最好调用setSoTimeout()方法设置接收数据的超时时间,如果超过了规定的时间Socket还没有接收到返回的数据的话,就中断阻塞,Socket会抛出”超时异常”。
(4) 解决读取输入流阻塞问题;乱码问题
Socket在读数据的时候是阻塞式的,如果没有读到数据程序会一直阻塞,通常在输出流中写入数据完成后,再写入一个特征标志,这样在输入流读取到这个特征标志的时候跳出循环。比如BufferedReader的readLine方法是一次读一行,这个方法是阻塞的,直到它读到了一行数据为止程序才会继续往下执行,所以在对应的输出流写完数据后,要再写入一个换行符,才不会导致阻塞。写入数据时使用的编码要和读取数据时使用的编码一致,否则写入的数据,在读出之后可能显示乱码。
参考链接: