使用网络流实现多人聊天室
实现多人聊天室,运用到网络流,线程,IO流等知识点.
什么是网络流,如何使用网络流,附上链接:java网络编程 - Tmillion - 博客园 (cnblogs.com)
分析:
实现多个人聊天,就有多个客户端,在点对点通信里,由服务器端指明端口号,在客户端请求服务器地址,端口,与服务器进行连接即能完成通信.
那么多个人在一个群里聊天,怎么让多个人连接到同一个服务器呢?在服务器端使用线程,有一个客户端连接,就创建一个线程与该客户端连接
实现:
每个客户端创建两个线程,一个用来发送消息,一个用来接收消息,
这里的服务器端就负责转发消息,里面的线程也需要完成读写操作,顺序是先接收信息,然后写出去
下面展示代码
客户端:
public class Client3 { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1",8888);// new SendThread(socket).start();//发送线程 new ReceiveThread("服务器",socket).start();//接收线程 }
127.0.0.1表示本地服务器地址,8888为端口号,创建两个线程来负责读和写操作.
客户端发送消息:
public class SendThread extends Thread { private Socket socket; private boolean flag = true; Scanner input = new Scanner(System.in); public SendThread(Socket socket) { this.socket = socket; } //一直在写 @Override public void run() { while(flag){ send(input.next()); } } //发送 public void send(String str){ BufferedWriter bw = null; try { OutputStream out = socket.getOutputStream(); bw = new BufferedWriter(new OutputStreamWriter(out)); //发送数据 bw.write(str); bw.newLine(); //写了换行符 bw.flush(); //刷新缓存区 } catch (IOException e) { flag = false; CloseUtil.close(bw,socket); } } }
发送消息相当于IO流中的写操作
客户端接收消息:
public class ReceiveThread extends Thread{ private Socket socket; private boolean flag = true; public ReceiveThread(String name, Socket socket) { super(name); this.socket = socket; } //一直读 @Override public void run() { while(flag){ //读 接收 String receive = receive(); System.out.println(receive); } } //接收方法 public String receive() { BufferedReader br = null; try { InputStream in = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(in)); //接收数据 String line = br.readLine(); //阻塞方法, 读到行结尾 换行符 return this.getName()+"说:"+line; } catch (IOException e) { flag = false; CloseUtil.close(br,socket); } return ""; } }
服务器端:
public class Server4 { public static List<Socket> clients = new ArrayList<>(); public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8888); int i = 1; while(true){ Socket client = serverSocket.accept();//阻塞 System.out.println("有客户端连接"); clients.add(client); //有一个客户端连接,创建一个线程与该客户端连接 Server4Thread server4Thread = new Server4Thread("客户端"+i,client); //启动线程 server4Thread.start(); i++; } } }
在服务器端创建ServerSocket,写一个死循环,如果一直有客户端接入,就不断创建线程来连接
服务器转发(先接收后写出):
public class Server4Thread extends Thread{ private Socket socket; public Server4Thread(String name, Socket socket) { super(name); this.socket = socket; } @Override public void run() { //一直先读后发 while(true){ sendOther(receive()); } } //接收 public String receive(){ BufferedReader br = null; try { InputStream in = socket.getInputStream(); //把它变为字节流---->读取字节流 br = new BufferedReader(new InputStreamReader(in)); //接收数据 String line = br.readLine(); //阻塞方法, 读到行结尾 换行符 return this.getName()+"说:"+line; } catch (IOException e) { CloseUtil.close(br,socket); } return ""; } //发送,转发给其他人 public void sendOther(String str){ List<Socket> clients = Server4.clients; for (Socket client : clients) { //排除自己 if(client != socket){ send(str,client); } } } //发送 public void send(String str,Socket socket){ BufferedWriter bw = null; try { OutputStream out = socket.getOutputStream(); bw = new BufferedWriter(new OutputStreamWriter(out)); //发送数据 bw.write(str); bw.newLine(); //写了换行符 bw.flush(); //刷新缓存区 } catch (IOException e) { CloseUtil.close(bw,socket); } } }
模拟多个人,这里的客户端需要开启多遍,设置:
1.根据图片,点击蓝色那栏
2.选中要运行多次的程序,勾选右上角的Allow parallel run,最后选中Apply,然后点击OK,完成!