javasocket+多线程实现控制台聊天室

行者 行者     2022-08-02     688

关键词:

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827212.html 

 另:具体代码实现已移植github: https://github.com/ygj0930/Chat-Room-in-Java  ,大家fork之余记得给我个star呀~

聊天室程序的结构图:

 

架构解释:

   Server服务器相当于一个中转站,Client客户端程序传送信息到服务器,服务器再把信息分发到其他客户端上,实现即时通信。

 

所需技术:

1:数据传输。

     服务器与客户端之间的信息传递,都通过数据通道实现,有一个客户端连接到服务器,就有一条数据通道架设于该客户端和服务器之间。

这条数据通道通过Socket来实现:每个客户端通过一个socket与服务器建立连接,这是通道的一个“端点”。而服务器端ServerSocket一旦检测到有客户端接入,accept()方法就会马上返回一个socket对象与客户端的socket对接起来,这是通道的另一个“端点”。“两点建立一条直线”,当然,这里不一定是直的(废话)。总之,一条像水管一样的通道就这样把一个客户端与服务器联系起来了。之后的事情,就是把我们要传输的数据,通过数据通道传输,如同水管运水一样,数据就是那些水。

2:持续监听。

     即时聊天要求某一客户端(聊天者)敲出来的话要立刻更新到连接到该服务器上的所有客户端的界面上,这个简单,学过while循环的人应该都能立刻想到:我用一个while()语句持续地从数据通道检测数据不就成了?一旦数据通道有信息,马上把它取出来,在客户端显示就ok了。

      然而!这事儿还没完。每个客户端都要保持持续接收用户输入的状态。你总不能一个客户端只发送一次信息就关闭掉了吧?

      那么问题来了,又要保持持续监听服务器端传过来的信息,又要保持持续监听键盘输入,那这俩while循环到底怎么安排呢?

     这里最容易犯的错误就是,用一个while循环嵌套了另一个while循环。比如下面的代码:

 

 while ((msg1 = br.readLine()) != null) { 
      System.out.println(msg1); 
      while (true) { 
      msg2 = re.readLine(); 
      pw.println(msg2); 
   }

 

 

 

   外层循环持续监听数据通道,一旦有服务器端传过来的信息,就提取出来显示到客户端。内层循环持续监听键盘输入,有则通过pw(数据通道,等下会有源码)传输给服务器。

   这里错误在于,内层循环是死循环,不会停止,所以会出现客户端不停输入信息发送到服务器,然而信息却没有更新到其他的客户端去。因为客户端代码停留在内层循环,没有出去执行监听并提取数据通道信息那一部分代码。

     还有一种案例,就是在客户端输入信息,却没有显示出来,狂按键盘也没见打出一个字。但是把服务器程序关闭后却又在客户端程序窗口看到一大堆刚才输入的信息。

     这种错误的原因与上面相反,是监听数据通道的while循环阻塞了下一个while循环(接收键盘输入部分)的执行。代码如下:

    

BufferedReader br = new BufferedReader(new InputStreamReader(socket .getInputStream())); 

    String msg1; 

    while ((msg1 = br.readLine()) != null) { 
             System.out.println(msg1); 
   } 

    BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); 
    String msg2; 
    while (true) { 
        msg2 = re.readLine(); 
        pw.println(msg2); 
}

 

  上面一个while循环持续监听数据通道(服务器向客户端传送信息),保持在等待接收信息状态,导致下面的代码没有执行,所以客户端不能接收用户输入,狂敲键盘也没用。

而关闭服务器程序后,数据通道断了,就不再监听,转而运行到了下面的while循环,所以就能接收用户输入。

 

   那么正确的姿势是怎样的呢?那就是:并行。

   在一个while循环运行的同时,另一个while循环也运行。两个while循环没有先后之分。

   要实现并行,就需要用到多线程技术。【多线程是啥我就不讲了,基本上能做到这个项目的人都是学了多线程再来实践的吧哈哈哈~】

 

正确完整代码贴出来,仅供参考。如果你是用来应付老师布置的作业的,小心和别的同学撞车-_-:

Server.java:

import java.net.*;
import java.io.*;
import java.util.*;

public class Server {
    int port;
    List<Socket> clients;
    ServerSocket server;

    public static void main(String[] args) {
        new Server();
    }

    public Server() {
        try {

            port = 8080;
            clients = new ArrayList<Socket>();
            server = new ServerSocket(port);

            while (true) {
                Socket socket = server.accept();
                clients.add(socket);
                Mythread mythread = new Mythread(socket);
                mythread.start();
            }


        } catch (Exception ex) {
        }
    }

    class Mythread extends Thread {
        Socket ssocket;
        private BufferedReader br;
        private PrintWriter pw;
        public String msg;

        public Mythread(Socket s) {
            ssocket = s;
        }

        public void run() {

            try {
                br = new BufferedReader(new InputStreamReader(ssocket.getInputStream()));
                msg = "欢迎【" + ssocket.getInetAddress() + "】进入聊天室!当前聊天室有【"
                        + clients.size() + "】人";

                sendMsg();

                while ((msg = br.readLine()) != null) {

                    msg = "【" + ssocket.getInetAddress() + "】说:" + msg;
                    sendMsg();

                }
            } catch (Exception ex) {

            }
        }

        public void sendMsg() {
            try {
                System.out.println(msg);

                for (int i = clients.size() - 1; i >= 0; i--) {
                    pw = new PrintWriter(clients.get(i).getOutputStream(), true);
                    pw.println(msg);
                    pw.flush();
                }
            } catch (Exception ex) {
            }
        }
    }

}

 

Client.java:

        import java.io.*;
        import java.net.*;
        import java.util.*;

public class Client {
    public int port = 8080;
    Socket socket = null;

    public static void main(String[] args) {
        new Client();
    }

    public Client() {

        try {
            socket = new Socket("127.0.0.1", port);

            new Cthread().start();

            BufferedReader br = new BufferedReader(new InputStreamReader(socket
                    .getInputStream()));
            String msg1;
            while ((msg1 = br.readLine()) != null) {

                System.out.println(msg1);
            }
        } catch (Exception e) {
        }
    }

    class Cthread extends Thread {

        public void run() {
            try {

                BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
                PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
                String msg2;

                while (true) {

                    msg2 = re.readLine();
                    pw.println(msg2);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        }
    }

}
 

 

 

老习惯,来个总结:用Socket构建数据通道(InputStream/OutputStream),用多线程同时运行两个while实现监听与更新,就是聊天室的技术所在。

(本人新手,恳请老码农们指正。感激不尽!若需要转载与交流,请于评论处留言告知我一声,谢谢)

字节码学院之javasocket控制台聊天室(代码片段)

学了个把月基础,终于写出了一个双工通信的控制台版本的聊天室了,废话不说啦,直接上代码:服务端代码packagecom.zijiemaedu.socketdemo;importjava.io.*;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.Scanner;/***@author:Mr-zhang*@create: 查看详情

javasocket编程实现群聊(超详细)(代码片段)

Javasocket编程实现群聊最终效果文末有完整代码,创作不易,点个赞再走吧~客户端之间的交流有人退出群聊时,减少在线人数实现流程1、项目结构即原理分析功能实现多客户之间聊天实时统计在线人数图形化界面创建... 查看详情

多线程+socket实现多人聊天室

最近在学习多线程的时候打算做一个简单的多线程socke聊天的程序,结果发现网上的代码都没有完整的实现功能,所以自己实现了一个demo:demo功能大致就是,有一个服务端负责信息转发,多个客户端发送消息,当一个客户端发... 查看详情

javasocket一对多通信如何实现?

现在有一个服务器端,多个客户端,每当一个客户端接入服务器端的时候,服务器端就建立一个线程。现在问题,当服务器端发送消息的时候,只有一个客户端接受到了信息,其他连接到的客户端没有反映。参考技术A【server端... 查看详情

javasocket编程学习笔记

 1.Socket通信简介及模型  JavaSocket可实现客户端--服务器间的双向实时通信。java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的client和server端。2.Socket通信实现方法 2.1 服务器端(非多线程)   用... 查看详情

javasocket详解(代码片段)

整理和总结了一下经常遇到的问题:1.客户端socket发送消息后,为什么服务端socket没有收到?2.使用while循环实现连续输入,是不是就是多线程模式?3.对多线程处理机制不是很明白,希望详细讲解?4.希... 查看详情

javasocket服务器端线程卡死

packageSocket;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.EOFException;importjava.io.IOException;importjava.net.BindException;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.ArrayList;importjava.util.List;publicclassChat_Server ServerSocketss=null; S... 查看详情

通过udp+多线程实现聊天功能

packageliu.net.udp;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetAddress;importj 查看详情

java实现的多人聊天(控制台输入)(代码片段)

在学习android时,想做一个多人聊天室,不知如何动手想先做一个纯java的简单多人聊天室,理理思路通过Socket套接字进行数据传输用到的知识点是:Socket,ServerSocket, 多线程 服务器程序:importjava.io.BufferedReader;i... 查看详情

多线程如何实现tcp多客户端聊天

...步应该怎样实现,我最大的问题是不知道怎么实现加入多线程的部分,我知道可以在服务器端用一个List把多个ServerSocket对象装起来,然后客户端没什么变化。但这具体点要怎么实现呢?求大哥哥大姐姐帮帮小弟。。。。参考技... 查看详情

javasocket编程--聊天小案例

  很久以前写过socket聊天室,都快忘完了,心血来潮又重新写一遍。服务器端:packagecom.fancy;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.io.OutputStream;imp 查看详情

带 GUI 的多线程客户端/服务器聊天室

】带GUI的多线程客户端/服务器聊天室【英文标题】:Multithreadedclient/serverChatroomwithGUI【发布时间】:2020-11-2301:16:37【问题描述】:我正在尝试使用Java制作带有gui的多线程客户端/服务器聊天室。目前,我能够创建一个正常运行的... 查看详情

多线程实现控制台打印“我爱你”10遍(代码片段)

packageThread;/****@authorAdministrator*创建ABC三条线程保证A线程打印我B线程打印爱C线程打印你循环10次*/publicclassDoSomeTestpublicstaticvoidmain(String[]args)throwsInterruptedExceptionObjecta=newObject();Objectb=newObject();O 查看详情

java编程实例-tcp聊天室代码实现(代码片段)

Tcp多人聊天室实现客户端:功能:数据发送数据接收技术:socket输入流和输出流多线程,客户端功能模块有两个线程聊天方式:群聊私聊私聊方法:@服务器用户id号:msg服务器:功能:数据转发用户注册技术:ServerSocket每一个用户对应的Sock... 查看详情

javasocket实战之六使用nio包实现socket通信(代码片段)

本文地址:http://blog.csdn.net/kongxx/article/details/7288896JavaSocket实战之一单线程通信JavaSocket实战之二多线程通信JavaSocket实战之三传输对象JavaSocket实战之四传输压缩对象JavaSocket实战之五使用加密协议传输对象前面几篇文章介绍了... 查看详情

一对多聊天室

/***实现一对多聊天室的服务端**/importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.net.ServerSocket;importjava.net.Socket;/***接受客户端发送消息的线程类* 查看详情

udp实现多线程聊天(代码片段)

...ta.encode(‘gb2312‘),addr)1920if__name__==‘__main__‘:21#创建两个线程22t1=Thread(target=sent_data)23t2=Thread(target=recv_data)24t1.start()25t2.start()26t1.join()27t2.join()  查看详情

具有消息(文本)和文件传输的 Java Socket 多用户聊天应用程序

】具有消息(文本)和文件传输的JavaSocket多用户聊天应用程序【英文标题】:JavaSocketMultiuserchatappwithbothmessage(text)andfiletransfer【发布时间】:2021-12-2202:45:22【问题描述】:我是Java新手。我正在通过制作一个聊天应用程序来学习... 查看详情