网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。
java.net包中JavaSE的API包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。
java.net包中提供了两种常见的网络协议的支持:
TCP:TCP是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称TCP/IP。
UDP:UDP是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据报。
本案例以TCP协议为例,结合多线程,实现一个多人同时聊天的聊天室。
释放资源:
Utils.java
1 package com.bjwyj.chat; 2 3 import java.io.Closeable; 4 5 public class Utils { 6 /** 7 * 释放资源 8 */ 9 public static void close(Closeable... targets) { 10 for(Closeable target:targets) { 11 try { 12 if(target!=null) { 13 target.close(); 14 } 15 }catch(Exception e) { 16 e.printStackTrace(); 17 } 18 } 19 } 20 }
服务器端:
Chat.java
1 package com.bjwyj.chat; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 import java.util.concurrent.CopyOnWriteArrayList; 9 10 /** 11 * 在线聊天室:服务端 12 * 目标:加入容器实现群聊和私聊 13 * 14 * @author 吴永吉 15 * 16 */ 17 public class Chat { 18 private static CopyOnWriteArrayList<Channel> all = new CopyOnWriteArrayList<>(); 19 public static void main(String[] args) throws IOException { 20 System.out.println("------server------"); 21 //1.指定端口:使用ServerSocket创建服务器 22 ServerSocket server = new ServerSocket(9999); 23 //2.阻塞式等待连接accept 24 while(true) { 25 Socket client = server.accept(); 26 System.out.println("一个客户端建立了连接"); 27 Channel c = new Channel(client); 28 all.add(c); //管理所有的成员 29 new Thread(c).start(); 30 } 31 } 32 //一个客户代表一个Channel 33 static class Channel implements Runnable{ 34 private DataInputStream dis; 35 private DataOutputStream dos; 36 private Socket client; 37 private boolean isRunning; 38 private String name; 39 40 public Channel(Socket client) { 41 isRunning = true; 42 this.client = client; 43 try { 44 dis = new DataInputStream(client.getInputStream()); 45 dos = new DataOutputStream(client.getOutputStream()); 46 //获取名称 47 this.name = receive(); 48 //欢迎你的到来 49 this.send("欢迎上线"); 50 this.sendOthers(this.name+"上线啦!",true); 51 }catch(Exception e) { 52 release(); 53 } 54 } 55 56 //接收消息 57 public String receive() { 58 String msg = ""; 59 try { 60 msg = dis.readUTF(); 61 } catch (IOException e) { 62 System.out.println("-------Chat receive------"); 63 release(); 64 } 65 return msg; 66 } 67 //发送消息 68 public void send(String msg) { 69 try { 70 dos.writeUTF(msg); 71 dos.flush(); 72 } catch (IOException e) { 73 System.out.println("--------Chat send-------"); 74 release(); 75 } 76 } 77 /** 78 * 群聊:获取自己的消息,发给其他人 79 * 私聊:约定数据格式:@xxx:msg 80 * @param msg 81 */ 82 public void sendOthers(String msg,boolean isSys) { 83 boolean isPrivate = msg.startsWith("@"); 84 if(isPrivate) { //私聊 85 int idx = msg.indexOf(":"); 86 //获取目标和数据 87 String targetName = msg.substring(1,idx); 88 msg = msg.substring(idx+1); 89 for(Channel other:all) { 90 if(other.name.equals(targetName)) { //目标 91 other.send(this.name+"悄悄的对你说:"+msg); 92 break; 93 } 94 } 95 }else { //群聊 96 for(Channel other:all) { 97 if(this==other) { //自己 98 continue; 99 } 100 if(!isSys) { 101 other.send(this.name+"对所有人说:"+msg); //群聊消息 102 }else { 103 other.send(msg); //系统消息 104 } 105 } 106 } 107 } 108 //关闭资源 109 public void release() { 110 this.isRunning = false; 111 Utils.close(dis,dos,client); 112 //退出 113 all.remove(this); 114 sendOthers(this.name+"下线了!",true); 115 } 116 117 @Override 118 public void run() { 119 while(isRunning) { 120 String msg = receive(); 121 if(!msg.equals("")) { 122 //send(msg); 123 sendOthers(msg,false); 124 } 125 } 126 } 127 } 128 }
客户端:
Send.java
1 package com.bjwyj.chat; 2 3 import java.io.BufferedReader; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.net.Socket; 8 9 /** 10 * 使用多线程封装了客户发送端: 11 * 1.发送消息 12 * 2.从控制台获取消息 13 * 3.释放资源 14 * 4.重写run 15 * @author 吴永吉 16 * 17 */ 18 public class Send implements Runnable{ 19 private BufferedReader console; 20 private DataOutputStream dos; 21 private Socket client; 22 private boolean isRunning; 23 private String name; 24 25 public Send(Socket client,String name) { 26 isRunning = true; 27 this.client = client; 28 this.name = name; 29 console = new BufferedReader(new InputStreamReader(System.in)); 30 try { 31 dos = new DataOutputStream(client.getOutputStream()); 32 //发送名称 33 send(name); 34 } catch (IOException e) { 35 System.out.println("------Client Send------"); 36 this.release(); 37 } 38 } 39 40 @Override 41 public void run() { 42 while(isRunning) { 43 String msg = this.getStringFromConsole(); 44 if(!msg.equals("")) { 45 this.send(msg); 46 } 47 } 48 } 49 50 /** 51 * 发送消息 52 */ 53 private void send(String msg) { 54 try { 55 dos.writeUTF(msg); 56 dos.flush(); 57 } catch (IOException e) { 58 System.out.println("------Client send------"); 59 release(); 60 } 61 } 62 63 /** 64 * 从控制台获取消息 65 */ 66 private String getStringFromConsole() { 67 try { 68 return console.readLine(); 69 } catch (IOException e) { 70 System.out.println("------Client console------"); 71 release(); 72 } 73 return ""; 74 } 75 76 //释放资源 77 private void release() { 78 this.isRunning = false; 79 Utils.close(dos,client); 80 } 81 }
Receive.java
1 package com.bjwyj.chat; 2 3 import java.io.DataInputStream; 4 import java.io.IOException; 5 import java.net.Socket; 6 7 /** 8 * 使用多线程封装了客户接收端 9 * 1.接收消息 10 * 2.释放资源 11 * 3.重写run 12 * @author 吴永吉 13 * 14 */ 15 public class Receive implements Runnable{ 16 private DataInputStream dis; 17 private Socket client; 18 private boolean isRunning; 19 20 public Receive(Socket client) { 21 this.isRunning = true; 22 this.client = client; 23 try { 24 dis = new DataInputStream(client.getInputStream()); 25 } catch (IOException e) { 26 System.out.println("------Client Receive------"); 27 this.release(); 28 } 29 } 30 31 //接收消息 32 public String receive() { 33 String msg = ""; 34 try { 35 msg = dis.readUTF(); 36 } catch (IOException e) { 37 System.out.println("-------Receive receive------"); 38 release(); 39 } 40 return msg; 41 } 42 43 @Override 44 public void run() { 45 while(isRunning) { 46 String msg = this.receive(); 47 if(!msg.equals("")) { 48 System.out.println(msg); 49 } 50 } 51 } 52 53 //释放资源 54 private void release() { 55 this.isRunning = false; 56 Utils.close(dis,client); 57 } 58 }
Client.java
1 package com.bjwyj.chat; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.Socket; 7 import java.net.UnknownHostException; 8 9 /** 10 * 在线聊天室:客户端 11 * 12 * @author 吴永吉 13 * 14 */ 15 public class Client { 16 public static void main(String[] args) throws UnknownHostException, IOException { 17 System.out.println("------client------"); 18 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 19 System.out.println("请输入名称:"); 20 String name = br.readLine(); 21 //建立连接:使用Socket创建客户端+服务器的地址和端口号 22 Socket client = new Socket("localhost",9999); 23 //客户端发送消息 24 new Thread(new Send(client,name)).start(); 25 //获取消息 26 new Thread(new Receive(client)).start(); 27 } 28 }
运行结果:
原文地址:https://www.cnblogs.com/wuyongji/p/10659540.html
时间: 2024-11-08 11:35:40