JavaSE版聊天室项目

清疚 2022-06-02 00:40 238阅读 0赞

JavaSE聊天室小项目

使用TCP编程实现客户端和服务器端的不断交互

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.Socket;
  5. import java.net.UnknownHostException;
  6. import java.util.Scanner;
  7. /**
  8. * 客户端
  9. * */
  10. public class ChatRoomClient {
  11. public static void main(String[] args) {
  12. try {
  13. //创建Socket对象
  14. Socket s = new Socket("127.0.0.1",12345);
  15. //获取客户端通道的输出和输入流
  16. InputStream in = s.getInputStream();
  17. OutputStream out = s.getOutputStream();
  18. //创建键盘录入对象
  19. Scanner sc = new Scanner(System.in);
  20. //客户端不断的发送消息
  21. while(true) {
  22. System.out.println("请输入消息:");
  23. String msg = sc.nextLine();
  24. //使用输出流发送过去
  25. out.write(msg.getBytes());
  26. //客户端读取服务器发送的消息
  27. byte [] bys = new byte [1024];
  28. int len = in.read(bys);
  29. String msgStr = new String(bys, 0, len);
  30. System.out.println(msgStr);
  31. }
  32. } catch (UnknownHostException e) {
  33. e.printStackTrace();
  34. } catch (IOException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. import java.io.IOException;
  40. import java.io.InputStream;
  41. import java.io.OutputStream;
  42. import java.net.ServerSocket;
  43. import java.net.Socket;
  44. import java.util.Scanner;
  45. /**
  46. * 服务器端
  47. * */
  48. public class ChatRoomServer {
  49. public static void main(String[] args) {
  50. try {
  51. //创建服务器端Socket对象
  52. ServerSocket ss = new ServerSocket(12345);
  53. //监听客户端
  54. Socket s = ss.accept();
  55. //获取服务器端通道的输出和输入流
  56. InputStream in = s.getInputStream();
  57. OutputStream out = s.getOutputStream();
  58. //创建键盘录入对象
  59. Scanner sc = new Scanner(System.in);
  60. //服务器端不断的读取消息和回复消息
  61. while(true) {
  62. //读消息
  63. byte [] bys = new byte [1024];
  64. int len = in.read(bys);
  65. String msg = new String(bys, 0, len);
  66. System.out.println(msg);
  67. //回复消息
  68. System.out.println("请回复消息:");
  69. String msgStr = sc.nextLine();
  70. out.write(msgStr.getBytes());
  71. }
  72. } catch (IOException e) {
  73. e.printStackTrace();
  74. }
  75. }
  76. }

这样做有问题,客户端和服务器端的读发消息都在一个线程,可能会出现互相等待的问题

改进:将读消息放在子线程里面(规定)

客户端

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.Socket;
  5. import java.net.UnknownHostException;
  6. import java.util.Scanner;
  7. /**
  8. * 客户端
  9. * @author dreamer_96
  10. */
  11. public class ChatRoomClient {
  12. public static void main(String[] args) {
  13. try {
  14. //创建Socket对象
  15. Socket s = new Socket("127.0.0.1",12345);
  16. //获取客户端通道的输出和输入流
  17. InputStream in = s.getInputStream();
  18. OutputStream out = s.getOutputStream();
  19. //创建键盘录入对象
  20. Scanner sc = new Scanner(System.in);
  21. //开启读消息子线程
  22. ClientThread ct = new ClientThread(in);
  23. ct.start();
  24. //客户端不断的发送消息
  25. while(true) {
  26. System.out.println("请输入消息:");
  27. String msg = sc.nextLine();
  28. //使用输出流发送过去
  29. out.write(msg.getBytes());
  30. }
  31. } catch (UnknownHostException e) {
  32. e.printStackTrace();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }

客户端读消息子线程

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. /**
  4. * 客户端读取消息的子线程
  5. * @author dreamer_96
  6. */
  7. public class ClientThread extends Thread {
  8. private InputStream in ;
  9. public ClientThread(InputStream in) {
  10. this.in = in;
  11. }
  12. @Override
  13. public void run() {
  14. try {
  15. while(true) {
  16. //客户端不断读取服务器发送的消息
  17. byte [] bys = new byte [1024];
  18. int len = in.read(bys);
  19. String msgStr = new String(bys, 0, len);
  20. System.out.println(msgStr);
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

服务器端

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. import java.util.Scanner;
  7. /**
  8. * 服务器端
  9. * @author dreamer_96
  10. */
  11. public class ChatRoomServer {
  12. public static void main(String[] args) {
  13. try {
  14. //创建服务器端Socket对象
  15. ServerSocket ss = new ServerSocket(12345);
  16. //监听客户端
  17. Socket s = ss.accept();
  18. //获取服务器端通道的输出和输入流
  19. InputStream in = s.getInputStream();
  20. OutputStream out = s.getOutputStream();
  21. //创建键盘录入对象
  22. Scanner sc = new Scanner(System.in);
  23. //开启子线程
  24. ServerThread st = new ServerThread(in);
  25. st.start();
  26. //服务器端不断的读取消息和回复消息
  27. while(true) {
  28. //回复消息
  29. System.out.println("请回复消息:");
  30. String msgStr = sc.nextLine();
  31. out.write(msgStr.getBytes());
  32. }
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }

服务器端读消息子线程

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. /**
  4. * 服务器端读取消息的子线程
  5. * @author dreamer_96
  6. */
  7. public class ServerThread extends Thread {
  8. private InputStream in;
  9. public ServerThread(InputStream in) {
  10. this.in= in ;
  11. }
  12. @Override
  13. public void run() {
  14. try {
  15. while(true) {
  16. //读取客户端发送的消息
  17. byte [] bys = new byte [1024];
  18. int len = in.read(bys);
  19. String msg = new String(bys, 0, len);
  20. System.out.println(msg);
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

使用ArrayList集合存储Socket对象

服务器端

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. import java.util.ArrayList;
  7. import java.util.Scanner;
  8. /**
  9. * 服务器端
  10. * @author dreamer_96
  11. */
  12. public class ChatRoomServer {
  13. public static void main(String[] args) {
  14. try {
  15. //创建服务器端Socket对象
  16. ServerSocket ss = new ServerSocket(12345);
  17. //创建ArrayList集合;分别保存每个通道内的Socket对象
  18. ArrayList<Socket> list = new ArrayList<Socket>();
  19. System.out.println("等待客户端连接,请稍后....");
  20. int i = 1;
  21. while(true) {
  22. //监听客户端
  23. Socket s = ss.accept();
  24. System.out.println("第"+(i++)+"个客户端已连接");
  25. //服务器一监听到客户端,就跳添加到集合中
  26. list.add(s);
  27. //获取服务器端通道的输出和输入流
  28. InputStream in = s.getInputStream();
  29. OutputStream out = s.getOutputStream();
  30. //开启子线程
  31. // ServerThread st = new ServerThread(in);
  32. ServerThread st = new ServerThread(s,list);
  33. st.start();
  34. }
  35. /*//创建键盘录入对象
  36. Scanner sc = new Scanner(System.in);
  37. //服务器端不断的读取消息和回复消息
  38. while(true) {
  39. //回复消息
  40. System.out.println("请回复消息:");
  41. String msgStr = sc.nextLine();
  42. out.write(msgStr.getBytes());
  43. }*/
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }

服务器端读消息子线程

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.Socket;
  5. import java.util.ArrayList;
  6. /**
  7. * 服务器端读取消息的子线程
  8. * @author dreamer_96
  9. */
  10. public class ServerThread extends Thread {
  11. /*private InputStream in;
  12. public ServerThread(InputStream in) {
  13. this.in= in ;
  14. }*/
  15. private Socket s;
  16. private ArrayList<Socket> list;
  17. public ServerThread(Socket s, ArrayList<Socket> list) {
  18. this.s = s;
  19. this.list = list;
  20. }
  21. @Override
  22. public void run() {
  23. try {
  24. //获取通道内的输入输出流
  25. InputStream in = s.getInputStream();
  26. OutputStream out = s.getOutputStream();
  27. while(true) {
  28. //读取客户端发送的消息
  29. byte [] bys = new byte [1024];
  30. int len = in.read(bys);
  31. String msg = new String(bys, 0, len);
  32. //msg现在的格式: 接收者:消息内容:发送者
  33. System.out.println(msg);
  34. //将消息拆分
  35. String[] msgs = msg.split(":");
  36. Socket socket = list.get(Integer.parseInt(msgs[0]));
  37. //获取输出流,写过去
  38. OutputStream os = socket.getOutputStream();
  39. os.write((msgs[2]+"对你说"+msgs[1]).getBytes());
  40. }
  41. } catch (IOException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. }

客户端不变,这样做依旧有缺点,我们要遵循开发规则 “高内聚,低耦合” ;所以我们使用HashMap集合添加用户并且增加服务器保存用户的子线程SaveUserThread

发表评论

表情:
评论列表 (有 0 条评论,238人围观)

还没有评论,来说两句吧...

相关阅读

    相关 项目介绍】IM聊天

    IM你可能没听过,但是网页版的微信你一定不会陌生吧?其实网页版微信就是IM中的一种形式。 这里的IM 是 Instant Message 就是一个允许多人通过网络进行即时通