java多线程聊天室_Java Socket 多线程聊天室

本文介绍了一个基于Java Socket实现的多线程聊天室。客户端通过Socket与服务器建立连接,每个用户有两个线程分别负责发送和接收消息。服务器端采用C/S架构,维护用户线程列表和消息列表,确保消息同步。服务器端的PrintClient线程用于调度消息发送,需要注意线程同步问题,防止出现错误。
摘要由CSDN通过智能技术生成

本来这次作业我是想搞个图形界面的,然而现实情况是我把题意理解错了,于是乎失去了最初的兴致,还是把程序变成了功能正确但是“UI”不友好的console了,但是不管怎么样,前期的图形界面的开发还是很有收获的,毕竟讲真,想要把Java搞得有形有色的也是很不容易的,借助可视化的插件windowsBuilder,这个过程还是既exciting 又tiring的。

好吧 ,然而图形界面已经成为了历史,现在来说说这个功能正确的console 吧

我也是刚知道的Eclipse里面是可以跑好多个程序的,只要你的一个.java文件中有public static void main,他就能给你一个窗口,让你跑起来。只不过这些窗口堆叠在一起,需要自行选择不同的窗口进行IO操作。

总的思路是采用c/s的方式,client借助socket完成向server的发送和接受两个工作,当然了,为了体现出真实情况下的双工的特点,发送和接受是需要开两个线程的,也就是说,一个用户需要自己管理两个线程。server则相对来讲比较复杂,因为这里面涉及到了调度,server需要有发送消息给在线client的线程(这个线程要做的事情就是只要有消息就要把消息发到所有的用户的窗口),以及接受client发来的消息的线程(这个线程要做的事情就是将接收到的消息全部交给发送消息的线程,于是这两个线程之间的通信问题也是实现上的一个关键~),为了使得所有的用户消息是同步的,server需要管理一个用户线程的列表,用以实现用户的行为的控制,于是乎这就要求只要有用户请求连接服务器,服务器就要为用户新建一个线程,那么client 和server 之间靠什么来进行联系呢,那就是我们的socket了。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 importjava.io.BufferedReader;2 importjava.io.InputStreamReader;3 importjava.io.PrintWriter;4 importjava.net.Socket;5

6 public class Client extendsThread{7

8 private static String serverIp = "127.0.0.1";9 private static int serverPort = 8001;10

11 private Socket clientsSocket; //plays key role

12 private PrintWriter pw; //for send data

13 private BufferedReader br; //for receive data

14

15 publicClient(){16 try{17 clientsSocket = newSocket(serverIp, serverPort);18 pw = new PrintWriter(clientsSocket.getOutputStream(),true);19 br = new BufferedReader(newInputStreamReader(clientsSocket.getInputStream()));20 newreadServer();21

22 while(true){23 br = new BufferedReader(newInputStreamReader(System.in));24 String input =br.readLine();25 //System.out.println("this is the input :" + input);

26 pw.println(input);27 }28 } catch(Exception e) {29 e.printStackTrace();30 }31 }32

33 class readServer extendsThread{34 privateBufferedReader reader;35

36 publicreadServer(){37 try{38 reader = new BufferedReader(newInputStreamReader(clientsSocket.getInputStream()));39 start();40 } catch(Exception e) {41 e.printStackTrace();42 }43 }44

45 public voidrun(){46 try{47 while(true){48 String content =reader.readLine();49 if(content.equals("bye Client")){50 break;51 }52 else{53 System.out.println(content);54 }55 }56 } catch(Exception e) {57 e.printStackTrace();58 }59 }60 }61

62 public static void main(String[] args) throwsException{63 newClient();64 }65 }

Client codes

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 importjava.io.BufferedReader;2 importjava.io.InputStreamReader;3 importjava.io.PrintWriter;4 importjava.net.ServerSocket;5 importjava.net.Socket;6 importjava.util.ArrayList;7 importjava.util.LinkedList;8

9

10 public classServer {11

12 private static int port = 8001;13 private static boolean prit = false;14 private static ArrayList userList = new ArrayList<>();15 private static LinkedList messageList = new LinkedList<>();16 private static ArrayList threadsList = new ArrayList<>();17

18 privateServerSocket serverSocket;19

20 publicServer(){21 try{22 serverSocket = newServerSocket(port);23 newPrintClient();24

25 while(true){26 Socket socket =serverSocket.accept();27 newServerThread(socket);28 }29 } catch(Exception e) {30 e.printStackTrace();31 }32 }33

34 class PrintClient extendsThread{35 publicPrintClient(){36 start();37 }38

39 public voidrun(){40 while(true){41 try{42 Thread.sleep(10);43 } catch(Exception e) {44 e.printStackTrace();45 }46 if (prit == true){47 String msg =messageList.getFirst();48 //System.out.println("prepare to sent to Clent");

49 for(ServerThread sThread : threadsList){50 sThread.sendMessage(msg);51 }52 synchronized(messageList) {53 messageList.removeFirst();54 }55 prit = messageList.size() > 0 ? true : false;56 }57 }58 }59 }60

61 class ServerThread extendsThread{62 privateSocket client;63 privatePrintWriter pw;64 privateBufferedReader br;65 privateString user;66

67 publicServerThread(Socket socket){68 try{69 client =socket;70 pw = new PrintWriter(client.getOutputStream(),true);71 br = new BufferedReader(newInputStreamReader(client.getInputStream()));72 br.readLine();73

74 pw.println("connect success input your name ~");75 start();76 } catch(Exception e) {77 e.printStackTrace();78 }79 }80

81 public voidpushMessage(String msg){82 synchronized(messageList) {83 messageList.add(msg);84 }85 prit = true;86 }87

88 public voidsendMessage(String msg){89 pw.println(msg);90 }91

92

93 public voidrun(){94 try{95 int first = 1;96 String msg =br.readLine();97 while(!msg.equals("bye")){98 if (first == 1){99 user =msg;100 userList.add(user);101 threadsList.add(this);102 pw.println(user + " hello you can chat now ");103 this.pushMessage("Client " + "join in ~");104 //System.out.println("the prit is " + prit);

105 first--;106 }107 else{108 this.pushMessage("Client "+ "say :" +msg);109 //System.out.println("the prit is " + prit + " " + messageList.size());

110 }111 msg =br.readLine();112 //System.out.println(msg);

113 }114 pw.println("bye Client");115 } catch(Exception e) {116 e.printStackTrace();117 }finally{118 try{119 client.close();120 } catch(Exception e2) {121 e2.printStackTrace();122 }123 threadsList.remove(this);124 userList.remove(user);125 pushMessage(user + " leave ~");126 }127 }128 }129

130 public static void main(String[] srgs) throwsException{131 newServer();132 }133 }

Server codes

在这里注意一个问题,server端的PrintClient线程在run的过程中一定要有sleep的过程,否则会因为一开始的prit设置为false而在一直在while(true)的死循环中得不到更新,也就是说线程的同步出了错,从而会出现客户端无法收到信息的错误。还有一点要注意的是作为良好的编程习惯需要注意多个线程公用的变量要注意互斥操作,防止出现多线程中的“magic bugs”。同步与互斥,真是线程进程调度中的老大难啊,每次编程都要小心处理这两个问题,尽量避免不必要的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值