Java学习系列(十七)Java面向对象之开发聊天工具

来源:互联网 发布:深圳市华梦汽车网络 编辑:程序博客网 时间:2024/05/16 08:30

TCP通信
Socket --相当于“虚拟链路两端的插座”。Socket负责完成通信。
ServerSocket --它只负责“接收”连接。它用于产生Socket。

服务器端编程
1) 创建ServerSocket 对象,该对象负责“接收”连接。
2) 如果客户端有连接,ServerSocket 对象调用accept()方法返回一个Socket。
3)  通过IO流读取对方的信息,也可向对方发送数据。

客户端编程
1) new Socket()来建立与远程服务器的连接。
2) 通过IO流读取对方的信息,也可向对方发送数据。

举列说明1(简单通信):

/** * @author lhy * @description 服务器端 */public class ServerTest {public static void main(String[] args) {PrintStream ps = null;try {// ServerSocket只负责“接收”连接,20000为端口号(标识该应用程序)ServerSocket ss = new ServerSocket(20000);System.out.println("服务器端等待连接...");// 接收连接,它会阻塞线程Socket socket = ss.accept();// ----------------------下面统一面向IO编程--------------------------//ps = new PrintStream(socket.getOutputStream());ps.println("ServerTest你好");} catch (IOException e) {e.printStackTrace();} finally {ps.close();}}}

/** * @author lhy * @description 客户端 */public class ClientTest {public static void main(String[] args) {BufferedReader br = null;try {Socket socket = new Socket("192.168.0.8", 20000);// ----------------------下面统一面向IO编程--------------------------//br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = null;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();} finally {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}
举列说明2(控制台多人聊天):

服务器端:

public class ServerTest {static Set<Socket> clients = Collections.synchronizedSet(new HashSet<Socket>());public static void main(String[] args) {ServerSocket ss = null;try {ss = new ServerSocket(20000);System.out.println("服务器端等待连接...");while (true) {// 接收连接,它会阻塞线程Socket socket = ss.accept();clients.add(socket);// 启动线程new ServerThread(socket).start();}} catch (IOException e) {e.printStackTrace();} finally {try {ss.close();} catch (IOException e) {e.printStackTrace();}}}}// 单独封装一个线程类class ServerThread extends Thread {private Socket socket;public ServerThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {BufferedReader br = null;try {while (true) {// ----------------------下面统一面向IO编程--------------------------//br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = null;while ((line = br.readLine()) != null) {for (Socket s : ServerTest.clients) {PrintStream ps = new PrintStream(s.getOutputStream());ps.println(line);// 输出各个客户端对应的Socket}}}} catch (IOException e) {e.printStackTrace();} finally {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}
客户端:

public class ChatServer {// 定义一个线程安全的Set集合public static Set<Socket> clients = Collections.synchronizedSet(new HashSet<Socket>());public static void main(String[] args) throws IOException {// ServerSocket只负责“接受”连接,不能通信// 该服务器程序就在30002端口监听ServerSocket ss = new ServerSocket(20000);System.out.println("服务器等待连接...");while (true) { // 这样保证每个客户端有一条线程// 接受连接。它会阻塞线程Socket socket = ss.accept();// 只要连接成功,它会返回socketclients.add(socket);// 每次客户端连接进来,就将该客户端添加到clients集合中System.out.println("当前用户数量:" + clients.size());new ServerThread(socket).start();}}}class ServerThread extends Thread {private Socket socket;public ServerThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {// -----原來读文件,现在改为读网络,只要改节点try {BufferedReader socketBr = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = null;// line代表从网络中读取数据while ((line = socketBr.readLine()) != null) {for (Iterator<Socket> it = ChatServer.clients.iterator(); it.hasNext();) {Socket s = it.next();try {PrintStream ps = new PrintStream(s.getOutputStream());ps.println(line);// 输出到各客户端对应的socket} catch (SocketException ex) {it.remove();// 捕获到该socket的异常,即表明Socket已经断开                                                System.out.println("当前用户数量:" + ChatServer.clients.size());// ex.printStackTrace();}}}} catch (SocketException se) {ChatServer.clients.remove(socket);                        System.out.println("当前用户数量:" + ChatServer.clients.size()); } catch (Exception e) {e.printStackTrace();}}}
小结:

System.in :读取键盘输入。包装方法:BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

socket.getInputStream():读取网络。包装方法:BufferedReader socketBr = new BufferedReader(new InputStreamReader(socket.getInputStream()));

socket.getOutputStream():写入(输出到)网络。包装方法:PrintStream socketOut = new PrintStream(socket.getOutputStream());

System.out:输出到屏幕。

下面以之前IO讲的一张图来结束: