精华内容
下载资源
问答
  • 1. 用Java图形用户界面编写聊天室服务器端和客户端, 支持多个客户端连接到一个服务器。... 2. 可以实现群聊(聊天记录显示在所有客户端界面)。 3. 完成好友列表在各个客户端上显示。 4. 可以实现私人聊天,用户可以...
  • JavaSocket

    2020-03-14 22:07:58
    服务器端ServerSocket –创建对象: –ServerSocket(int port)创建绑定到特定端口的服务器套接字。 –常用方法: –Socket accept()侦听并接受到此套接字的连接。...–void close()关闭此套接字。...

    服务器端ServerSocket

    • –创建对象:

      -ServerSocket(int port)创建绑定到特定端口的服务器套接字。
      
    • –常用方法:

      --Socket accept()侦听并接受到此套接字的连接。 
      --void close()关闭此套接字。 
      

    客户端Socket

    • –创建对象:

      --Socket(String host, int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
      
    • -常用方法:

      --void close()关闭此套接字。
      --InputStream getInputStream()返回此套接字的输入流。 			
      --OutputStream getOutputStream() 返回此套接字的输出流。
      

    入门案例

    服务器端:
    //这个类表示Socket通信的服务器端
    public class Server {
    				public static void main(String[] args) {
    					try {
    						//1,在8000端口开启服务,等待客户端的连接  ServerSocket(int port)
    						//端口号:0~65535,其中0~1024被系统占用!!
    						ServerSocket server = new ServerSocket(8000);
    						//2,接收客户端的请求Socket accept()侦听并接受到此套接字的连接
    						Socket socket = server.accept();
    						//3,读取 客户端发来的数据
    						InputStream in = socket.getInputStream();
    						for (int i = 0; i < 5; i++) {//循环获取客户端的hello
    							char c = (char)in.read();//一个字节一个字节读取
    							System.out.print(c);//同行展示
    						}
    						//4、服务器把数据响应回客户端
    						OutputStream out = socket.getOutputStream();
    						out.write("java".getBytes());
    						out.flush();
    						
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    
    客户端:
    //这个类表示Socket通信的客户端
    			public class Client {
    				public static void main(String[] args) {
    					try {
    						//1,连接指定的服务器Socket(String host, int port)
    						//127.0.0.1 是本机的ip地址,实际工作中,要指定你想要访问的服务器的ip
    						Socket socket = new Socket("127.0.0.1",8000);
    						
    						//2,写出数据 发给服务器hello
    						OutputStream out = socket.getOutputStream();
    						out.write("hello".getBytes());//getBytes()把字符串转byte[]
    						out.flush();//刷新数据
    					
    						//3、解析服务器发回来的数据
    						InputStream in = socket.getInputStream();
    						for (int i = 0; i < 4; i++) {
    							char c = (char)in.read();//一个字节一个字节读取服务的数据
    							System.out.print(c);//同行展示
    						}
    						
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
    					
    				}
    			}
    
    展开全文
  • javaSocket

    2013-01-29 15:39:30
    java socket完整代码,含服务器和客户端。直接就可以运行!
  • JAVASocket编程资料汇总

    2019-07-22 15:24:06
    资源名称:JAVA Socket编程资料汇总资源目录:【】Java Socket 编程模拟Ftp【】Java Socket多人在线考试系统源程序【】JavaSocket线程实现多客户的机制以及获取ip地址【】JavaSocket通讯例程【】三步学会JavaSocket...
  • javasocket

    2009-12-18 21:34:37
    有关javasocket实现qq聊天功能,和javaMail的demo详解,还是多线程的
  • JAVASocket实现聊天室

    2020-04-25 11:36:22
    JAVASocket实现聊天室 文章目录JAVASocket实现聊天室Sokcet是什么JAVA SOCKET编程中的两个重要对象ServerSocket构造方法acceptbindcloseSocket构造方法getInputStream,getOutputStreamclose聊天室实现服务端实现...

    JAVASocket实现聊天室

    在这里插入图片描述

    Sokcet是什么

    socket本质上是两个端点之间的通信桥梁,两个端点相互连接,并且打开远程之间的网络IO,从而可以像对本地文件读写一样,JAVA对socket编程有着友好的支持,并且针对客户端和服务端抽象了不同的服务对象

    JAVA SOCKET编程中的两个重要对象

    JDK对Socket编程抽象了两个类ServerSocketSocket,分别封装了客户端和服务端的基本通信API

    ServerSocket

    JDK提供的服务端实现,主要用于监听服务端口,并且接受来自该端口的客户端请求,并且生成来自客户端的Socket对象。

    几个重要的方法:

    构造方法

    • ServerSocket()
    • ServerSocket(int port)
    • ServerSocket(int port,int backlog)
    • ServerSocket(int port,int backlog,InnetAddress bindAddr)

    上述构造方法设计到大致三个参数,port(端口),backlog请求客户端队列最大长度,bindAddr,将要绑定的IP实现,如果不指定默认本地IP。

    accept

    public Socket accept() throws IOException
    

    accept方法主要是在开启端口监听之后接受一个客户端的连接请求,如果没有请求进来,那么accept方法会一直阻塞,直到一个客户端的请求进入,accept方法在接受一个客户端的请求之后,会生成一个客户端的Socket对象,这个对象封装了客户端的IO请求。

    Socket client = serverSocket.accept();
    //对客户端的输入输出流
    OutputStream outputStream= client.getOutputStream();
    InputStream  inputStream = client.getInputStream();
    

    服务端可通过这个Socket对象获取对客户端的输入流和输出流,这样服务端就可以读取到客户端发送来的的消息,并且可以向客户端发送消息

    bind

    bind方法是真正实现socket套接字绑定IP和端口的实现,默认在ServerSocket的构造方法中会进行调用。

    public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
            ...
            try {
                bind(new InetSocketAddress(bindAddr, port), backlog);
            } catch(SecurityException e) {
                close();
                throw e;
            } catch(IOException e) {
                close();
                throw e;
            }
    }
           
    

    close

    当主动调用close方法后,服务器会释放当前绑定的端口,并且自动断开和所有客户端之间的连接,只有主动执行了ServerSocket的close()方法,isClosed()方法才返回true;否则,即使ServerSocket还没有和特定端口绑定,isClosed()方法也会返回false,这是因为服务端内部维护了一个closed变量,初始化为false,只有在调用了close方法才会将closed变量置为true

    Socket

    JDK提供的Socket套接字实现类,主要封装了端的IO操作,通过Socket对象我们可以实现对客户端及服务端的读写操作

    构造方法

    Socket(InetAddressaddress, int port);
    Socket(InetAddress address,int port, boolean stream);
    Socket(String host, intprot);
    Socket(String host, intprot, boolean stream);
    Socket(SocketImpl impl)
    Socket(String host, intport, InetAddress localAddr, Socket(InetAddress address,int port, InetAddress localAddr, int localPort)
    ServerSocket(int port);
    ServerSocket(int port, intbacklog);
    ServerSocket(int port, intbacklog, InetAddress bindAddr)
    

    其中address、host和port分别是双向连接中另一方的IP地址、 主机名和端口号,stream指明socket是流socket还是数据报 socket,localPort表示本地主机的端口号,localAddr和bindAddr是本地机器的地址(ServerSocket的主机地 址),impl是socket的父类,既可以用来创建serverSocket又可以用来创建Socket。count则表示服务端所能支持的最大连接数。

    Socket(String host, intprot)

    常用的构造方法默认指定host和port,表示要建立的远程连接的服务端IP和端口,在服务端开启端口监听之后,客户端可以得到一个连接到服务端的Socket对象,同时服务端也会得到一个连接到客户端的Socket对象,这样双方可基于Socket实现双向通信,发送并且接受消息

    getInputStream,getOutputStream

    获取对应端的输入输出流,当双方建立连接后,双方互相持有封装了对方IO操作的Sokcet对象,通过Socket对象获取对应的输入输出流实现双向通信。

    close

    当客户端的Socket关闭连接时,服务端与客户端的连接自动关闭,但是服务端会继续监听端口,等待新的连接进来。

    当服务端的Sokcet关闭连接时,服务端与所有客户端的连接将全部断开,并且释放对应监听接口

    聊天室实现

    服务端实现

    监听端口,调用accept方法等待客户端请求,另外新起两个线程分别针对客户端的读写进行处理

    public class Server {
    
        public static final Integer port =80;
    
        public static void main(String[] args) throws IOException {
            ServerSocket serverSocket = new ServerSocket(port);
            System.out.println("服务端监听 "+port+" 端口成功!,等待客户端连接");
            while (true){
                Socket client = serverSocket.accept();
                System.out.println("一个新的客户端进来了");
                new WriteHelper(client.getOutputStream(),"连接客户端成功!,可以畅所欲言了").start();
                new PrintHelper(client.getInputStream(),"服务端").start();
            }
        }
    
    
    }
    

    客户端实现

    绑定ip和端口,并且启动两个线程分别处理来自服务端的读写

    public class Client {
    
        public static void main(String[] args) throws IOException, InterruptedException {
            Socket socket = new Socket("127.0.0.1", 80);
            new WriteHelper(socket.getOutputStream(),"连接服务端成功!,可以畅所欲言了").start();
            new PrintHelper(socket.getInputStream(),"客户端").start();
        }
    }
    

    针对Socket的输入输出流实现单独线程处理,读写不互相收影响

    读线程实现

    主要针对Sokcet对象的输入流进行单独处理

    public class PrintHelper extends Thread{
    
        private InputStream inputStream;
        private String type;
    
        public PrintHelper(InputStream inputStream,String type) {
            this.inputStream=inputStream;
            this.type=type;
        }
    
        public void run() {
            byte[] bytes = new byte[1024];
            int length;
            try {
                while (true){
                    if (((length=inputStream.read(bytes))>1)){
                        String s = new String(bytes, 0, length);
                        LocalDateTime nowLocalDate = LocalDateTime.now();
                        String time = nowLocalDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        System.out.println("     "+time+"       "+type+" : "+s);
                        System.out.println("____________________________________________");
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    写线程实现

    主要针对Socket对象的输出流进行单独处理,

    public class WriteHelper extends Thread{
    
            private OutputStream outputStream;
    
            public WriteHelper(OutputStream outputStream,String message) {
                System.out.println(message);
                System.out.println("============================");
                this.outputStream=outputStream;
            }
    
            public void run() {
                Scanner scanner = new Scanner(System.in);
                while(true){
                    String next = scanner.next();
                    try {
                        outputStream.write(next.getBytes());
                        outputStream.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    }
    

    运行结果

    需要先启动服务端,开启端口监听,再启动客户端,实现IP加端口的连接

    启动服务端

    在这里插入图片描述

    客户端连接

    在这里插入图片描述

    在这里插入图片描述

    客户端发送消息

    在这里插入图片描述

    服务端收到消息

    在这里插入图片描述

    服务端回复消息

    在这里插入图片描述

    客户端收到消息

    在这里插入图片描述

    展开全文
  • javaSocket带界面聊天室

    2016-06-18 15:45:02
    javaSocket带界面聊天室
  • JavaSocket编程开发聊天室,附超详细注释

    千次阅读 多人点赞 2020-08-03 10:29:44
    JavaSocket编程开发聊天室 大二下册的JavaWeb课程设计,使用的是eclipse。 一、实现功能 登录:用Java图形用户界面编写聊天室服务器端和客户端,支持多个客户端连接到一个服务器。每个客户端能够输入账号。 ...

    用JavaSocket编程开发聊天室

    大二下册的JavaWeb课程设计,使用的是eclipse。

    一、实现功能

    1. 登录:用Java图形用户界面编写聊天室服务器端和客户端,支持多个客户端连接到一个服务器。每个客户端能够输入账号。

    2. 群聊:可以实现群聊(聊天记录显示在所有客户端界面)。

    3. 好友列表:完成好友列表在各个客户端上显示。

    4. 私聊:可以实现私人聊天,用户可以选择某个其他用户,单独发送信息,接受私聊消息方可以直接弹出消息框

    5. 踢人:服务器能够群发系统消息,能够强行让某些用户下线。

    6. 更新:客户端的上线下线要求能够在其他客户端上面实时刷新。

    二、思路概述

    • 分为服务器端和客户端。

    • 服务器端相当于一个转发器的功能,所有客户端的消息都先发给服务器端,由服务器端再转发给对应的客户端。

    • 不同类型的消息格式不同,服务器端根据消息的格式来判断事件类型,再执行相应的功能。

    服务器端

          因为运行的过程中随时会有客户端连上服务器,所以服务器端需要一个线程来等待客户端的链接。其次,每一个服务器端的用户随时都有可能和服务器就发送消息,因此每新增一个用户就需要为该用户建立一个聊天的线程
    服务器端还需要具备踢人、群发消息、发送消息的功能。这些功能的本质其实就是发送对应格式消息(消息格式见下文),只是发送的消息格式不同罢了。

    客户端

          客户端需要实现的主要功能是群发消息和私发消息,并且通过收到的消息格式判断服务器发送过来的消息,再进行响应的代码。

    三、消息格式

    1.上线 : login#nickName
    2.下线 : offline#nickName
    3.系统发消息 : All#content
    4.用户群发消息 : msg#nickName#content
    5.用户私发消息 : smsg#sender#receiver#content
    6.用户第一次私发消息 : fsmsg#sender#receiver#content
    7.服务器端为新加入的客户端建立好友列表 : users#nickName

    消息通过split("#")函数将字符串转换成数组,根据strs[0],即第一个值可以判断消息的类型,后面的值判断消息的客户端/发送者/接收者。

    四、运行结果

    客户端/服务器端界面:
    聊天室界面
    私聊界面:
    私聊界面

    五、源代码

    server.java:

    package chat;
    
    import javax.swing.*;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    
    class server extends JFrame implements Runnable, ListSelectionListener, ActionListener {
        private Socket s = null;
        private ServerSocket ss = null;
        private ArrayList<ChatThread> users = new ArrayList<ChatThread>(); //容量能够动态增长的数组
        DefaultListModel<String> dl = new DefaultListModel<String>();
        private JList<String> userList = new JList<String>(dl);//显示对象列表并且允许用户选择一个或多个项的组件。单独的模型 ListModel 维护列表的内容。
    
        private JPanel jpl = new JPanel();
        private JButton jbt = new JButton("踢出聊天室");
        private JButton jbt1 = new JButton("群发消息");
        //群发消息输入栏
        private JTextField jtf = new JTextField();
    
        public server() throws Exception{
            this.setTitle("服务器端");
            this.add(userList, "North");//放在北面
            this.add(jpl, "South");
    
            //仅将群发消息输入栏设为一栏
            jtf.setColumns(1);
            jpl.setLayout(new BorderLayout());
            jpl.add(jtf, BorderLayout.NORTH);
            jpl.add(jbt,BorderLayout.EAST);//踢出聊天室
            jpl.add(jbt1, BorderLayout.WEST);//群发消息
    
            //实现群发
            jbt1.addActionListener(this);
            //实现踢人
            jbt.addActionListener(this);
    
    
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            this.setLocation(400,100);
            this.setSize(500, 400);
            this.setVisible(true);
            this.setAlwaysOnTop(true);
            ss = new ServerSocket(9999);
            new Thread(this).start();//监听用户端的加入
        }
        @Override
        public void run() {
            while(true){
                try{
                    s = ss.accept();
                    ChatThread ct = new ChatThread(s); //为该客户开一个线程
                    users.add(ct); //将每个线程加入到users
                    //发送Jlist里的用户登陆信息,为了防止后面登陆的用户无法更新有前面用户的好友列表
                    ListModel<String> model = userList.getModel();//获取Jlist的数据内容
                    for(int i = 0; i < model.getSize(); i++){
                        ct.ps.println("USERS#" + model.getElementAt(i));
                    }
                    ct.start();
                }catch (Exception ex){
                    ex.printStackTrace();
                    javax.swing.JOptionPane.showMessageDialog(this,"服务器异常!");
                    System.exit(0);
                }
            }
        }
    
        //群发消息按钮点击事件监听
        @Override
        public void actionPerformed(ActionEvent e) {
            String label = e.getActionCommand();
            if(label.equals("群发消息")){
                handleAll();
            }else if(label.equals("踢出聊天室")){
                try {
                    handleExpel();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    
        public void handleAll(){
            if(!jtf.getText().equals("")){
                sendMessage("ALL#" + jtf.getText());
                //发送完后,是输入框中内容为空
                jtf.setText("");
            }
        }//群发消息
    
        public void handleExpel() throws IOException {
            sendMessage("OFFLINE#" + userList.getSelectedValuesList().get(0));
            dl.removeElement(userList.getSelectedValuesList().get(0));//更新defaultModel
            userList.repaint();//更新Jlist
        }//踢人
    
        public class ChatThread extends Thread{
            Socket s = null;
            private BufferedReader br = null;
            private PrintStream ps = null;
            public boolean canRun = true;
            String nickName = null;
            public ChatThread(Socket s) throws Exception{
                this.s = s;
                br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                ps = new PrintStream(s.getOutputStream());
            }
            public void run(){
                while(canRun){
                    try{
                        String msg = br.readLine();//接收客户端发来的消息
                        String[] strs = msg.split("#");
                        if(strs[0].equals("LOGIN")){//收到来自客户端的上线消息
                            nickName = strs[1];
                            dl.addElement(nickName);
                            userList.repaint();
                            sendMessage(msg);
                        }else if(strs[0].equals("MSG") || strs[0].equals("SMSG") || strs[0].equals("FSMSG")){
                            sendMessage(msg);
                        }else if(strs[0].equals("OFFLINE")){//收到来自客户端的下线消息
                            sendMessage(msg);
                            //System.out.println(msg);
                            dl.removeElement(strs[1]);
                            // 更新List列表
                            userList.repaint();
                        }
                    }catch (Exception ex){}
                }
            }
        }
    
        public void sendMessage(String msg){  //服务器端发送给所有用户
            for(ChatThread ct : users){
                ct.ps.println(msg);
            }
        }
    
    	@Override
    	public void valueChanged(ListSelectionEvent e) {
    		// TODO 自动生成的方法存根
    		
    	}
    	
        public static void main(String[] args) throws Exception{
            new server();
        }
    }
    
    

    client.java:

    package chat;
    
    import javax.swing.*;
    import com.sun.org.apache.bcel.internal.generic.NEW;
    import java.awt.*;
    import java.awt.event.*;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    
    public class client extends JFrame implements Runnable,ActionListener {
        //north
        private JMenuBar bar = new JMenuBar();
        private JMenu menu = new JMenu("关于");
        private JMenuItem about = new JMenuItem("关于本软件");
        private JMenuItem exit = new JMenuItem("退出");
        JPanel north = new JPanel();
        //west
        JPanel west = new JPanel();
        DefaultListModel<String> dl = new DefaultListModel<String>();//用来修改JList
        private JList<String> userList = new JList<String>(dl);//用来展示和选择
        JScrollPane listPane = new JScrollPane(userList);
        //center
        JPanel center = new JPanel();
        JTextArea jta = new JTextArea(10,20);
        JScrollPane js = new JScrollPane(jta);
        JPanel operPane = new JPanel();//发送消息的操作面板
        JLabel input = new JLabel("请输入:");
        JTextField jtf = new JTextField(24);
    
        JButton jButton = new JButton("发消息");
    
        private JButton jbt = new JButton("发送消息");
        private JButton jbt1 = new JButton("私发消息");
        private BufferedReader br = null;
        private PrintStream ps = null;
        private String nickName = null;
    
        //私聊面板
        JTextArea jTextArea = new JTextArea(11,45);
        JScrollPane js1 = new JScrollPane(jTextArea);
        JTextField jTextField = new JTextField(25);
        String suser = new String();
        
        double MAIN_FRAME_LOC_X;//父窗口x坐标
        double MAIN_FRAME_LOC_Y;//父窗口y坐标
        
        boolean FirstSecret = true;//是否第一次私聊
        String sender=null;//私聊发送者的名字
        String receiver=null;//私聊接收者的名字
    
        public client() throws Exception{
            //north 菜单栏
            bar.add(menu);
            menu.add(about);
            menu.add(exit);
            about.addActionListener(this);
            exit.addActionListener(this);
            BorderLayout bl = new BorderLayout();
            north.setLayout(bl);
            north.add(bar,BorderLayout.NORTH);
            add(north,BorderLayout.NORTH);
            
            //east 好友列表
            Dimension dim = new Dimension(100,150);
            west.setPreferredSize(dim);//在使用了布局管理器后用setPreferredSize来设置窗口大小
            //Dimension dim2 = new Dimension(100,150);
            //listPane.setPreferredSize(dim2);
            BorderLayout bl2 = new BorderLayout();
            west.setLayout(bl2);
            west.add(listPane,BorderLayout.CENTER);//显示好友列表
            add(west,BorderLayout.EAST);
            userList.setFont(new Font("隶书",Font.BOLD,18));
            
            //center 聊天消息框  发送消息操作面板
            jta.setEditable(false);//消息显示框是不能编辑的
            jTextArea.setEditable(false);
    
            BorderLayout bl3 = new BorderLayout();
            center.setLayout(bl3);
            FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
            operPane.setLayout(fl);
            operPane.add(input);
            operPane.add(jtf);
            operPane.add(jbt);
            operPane.add(jbt1);
            center.add(js,BorderLayout.CENTER);//js是消息展示框JScrollPane
            center.add(operPane,BorderLayout.SOUTH);
            add(center,BorderLayout.CENTER);
    
            js.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);//需要时才显示滚动条
    
            //鼠标事件,点击
            jbt.addActionListener(this);
            jbt1.addActionListener(this);
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            //this.setAlwaysOnTop(true);
    
            nickName = JOptionPane.showInputDialog("用户名:");
            this.setTitle(nickName + "的聊天室");
            this.setSize(700,400);
            this.setVisible(true);
    
            Socket s = new Socket("127.0.0.1", 9999);
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            ps = new PrintStream(s.getOutputStream());
            new Thread(this).start();//run()
            ps.println("LOGIN#" + nickName);//发送登录信息,消息格式:LOGIN#nickName
            
            jtf.setFocusable(true);//设置焦点
            
            //键盘事件,实现当输完要发送的内容后,直接按回车键,实现发送
            //监听键盘相应的控件必须是获得焦点(focus)的情况下才能起作用
           jtf.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if(e.getKeyCode() == KeyEvent.VK_ENTER) {
                        ps.println("MSG#" + nickName + "#" +  jtf.getText());//发送消息的格式:MSG#nickName#message
                        //发送完后,是输入框中内容为空
                        jtf.setText("");
                    }
                }
            });
           
           //私聊消息框按回车发送消息
            jTextField.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if(e.getKeyCode() == KeyEvent.VK_ENTER) {
                        handleSS();
                    }
                }
            });
            
            //监听系统关闭事件,退出时给服务器端发出指定消息
            this.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    ps.println("OFFLINE#" + nickName);//发送下线信息,消息格式:OFFLINE#nickName
                }
            });
            
            this.addComponentListener(new ComponentAdapter() {//监听父窗口大小的改变     
                public void componentMoved(ComponentEvent e) {
                    Component comp = e.getComponent();							
                    MAIN_FRAME_LOC_X = comp.getX();
                    MAIN_FRAME_LOC_Y = comp.getY();			
                }
            }); 
        }
        
        public void run(){//客户端与服务器端发消息的线程
            while (true){
                try{
                    String msg = br.readLine();//读取服务器是否发送了消息给该客户端
                    String[] strs = msg.split("#");
                    //判断是否为服务器发来的登陆信息
                    if(strs[0].equals("LOGIN")){
                        if(!strs[1].equals(nickName)){//不是本人的上线消息就显示,本人的不显示
                            jta.append(strs[1] + "上线啦!\n");
                            dl.addElement(strs[1]);//DefaultListModel来更改JList的内容
                            userList.repaint();
                        }
                    }else if(strs[0].equals("MSG")){//接到服务器发送消息的信息
                        if(!strs[1].equals(nickName)){//别人说的
                            jta.append(strs[1] + "说:" + strs[2] + "\n");
                        }else{
                            jta.append("我说:" + strs[2] + "\n");
                        }
                    }else if(strs[0].equals("USERS")){//USER消息,为新建立的客户端更新好友列表
                        dl.addElement(strs[1]);
                        userList.repaint();
                    } else if(strs[0].equals("ALL")){
                        jta.append("系统消息:" + strs[1] + "\n");
                    }else if(strs[0].equals("OFFLINE")){
                    	if(strs[1].equals(nickName)) {//如果是自己下线的消息,说明被服务器端踢出聊天室,强制下线
                            javax.swing.JOptionPane.showMessageDialog(this, "您已被系统请出聊天室!");
                            System.exit(0);
                    	}
                        jta.append(strs[1] + "下线啦!\n");
                        dl.removeElement(strs[1]);
                        userList.repaint();
                    }else if((strs[2].equals(nickName) || strs[1].equals(nickName)) && strs[0].equals("SMSG")){
                    	if(!strs[1].equals(nickName)){
                        	jTextArea.append(strs[1] + "说:" + strs[3] + "\n");
                            jta.append("系统提示:" + strs[1] + "私信了你" + "\n");
                        }else{
                            jTextArea.append("我说:" + strs[3] + "\n");
                        }
                    }else if((strs[2].equals(nickName) || strs[1].equals(nickName)) && strs[0].equals("FSMSG"))
                    {
                    	sender = strs[1];
                    	receiver = strs[2];
                    	//接收方第一次收到私聊消息,自动弹出私聊窗口
                    	if(!strs[1].equals(nickName)) {
                    		FirstSecret = false;
                    		jTextArea.append(strs[1] + "说:" + strs[3] + "\n");
                    		jta.append("系统提示:" + strs[1] + "私信了你" + "\n");
                    		handleSec(strs[1]);
                    	}
                    	else {
                    		jTextArea.append("我说:" + strs[3] + "\n");
                    	}
                    }
                }catch (Exception ex){//如果服务器端出现问题,则客户端强制下线
                	javax.swing.JOptionPane.showMessageDialog(this, "您已被系统请出聊天室!");
                    System.exit(0);
                }
            }
        }
    
        
        @Override
        public void actionPerformed(ActionEvent e) {//鼠标点击事件
            String label = e.getActionCommand();
            if(label.equals("发送消息")){//群发
                handleSend();
            }else if(label.equals("私发消息") && !userList.isSelectionEmpty()){//未点击用户不执行
                suser = userList.getSelectedValuesList().get(0);//获得被选择的用户
                handleSec(suser);//创建私聊窗口
                sender = nickName;
                receiver = suser;
            }else if(label.equals("发消息")){
                handleSS();//私发消息
            }else if(label.equals("关于本软件")){
                JOptionPane.showMessageDialog(this, "1.可以在聊天框中进行群聊\n\n2.可以点击选择用户进行私聊");
            }else if(label.equals("退出")){
                JOptionPane.showMessageDialog(this, "您已成功退出!");
                ps.println("OFFLINE#" + nickName);
                System.exit(0);
            } else{
                System.out.println("不识别的事件");
            }
        }
    
        public void handleSS(){//在私聊窗口中发消息
        	String name=sender;
        	if(sender.equals(nickName)) {
        		name = receiver;
        	}
        	if(FirstSecret) {
        		ps.println("FSMSG#" + nickName + "#" + name + "#" + jTextField.getText());
            	jTextField.setText(""); 
            	FirstSecret = false;
        	}
        	else {
        		ps.println("SMSG#" + nickName + "#" + name + "#" + jTextField.getText());
        		jTextField.setText("");
        	} 	     
        }
    
        public void handleSend(){//群发消息
            //发送信息时标识一下来源
            ps.println("MSG#" + nickName + "#" +  jtf.getText());
            //发送完后,是输入框中内容为空
            jtf.setText("");
        }
    
        public void handleSec(String name){ //建立私聊窗口
            JFrame jFrame = new JFrame();//新建了一个窗口      
            JPanel JPL = new JPanel();
            JPanel JPL2 = new JPanel();
            FlowLayout f2 = new FlowLayout(FlowLayout.LEFT);
            JPL.setLayout(f2);
            JPL.add(jTextField);
            JPL.add(jButton);
            JPL2.add(js1,BorderLayout.CENTER);
            JPL2.add(JPL,BorderLayout.SOUTH);
            jFrame.add(JPL2);
    
            jButton.addActionListener(this);
            jTextArea.setFont(new Font("宋体", Font.PLAIN,15));
            jFrame.setSize(400,310);
            jFrame.setLocation((int)MAIN_FRAME_LOC_X+20,(int)MAIN_FRAME_LOC_Y+20);//将私聊窗口设置总是在父窗口的中间弹出
            jFrame.setTitle("与" + name + "私聊中");
            jFrame.setVisible(true);
    
            jTextField.setFocusable(true);//设置焦点
            
            jFrame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                	jTextArea.setText("");
                	FirstSecret = true;
                }
            });
        }//私聊窗口
    
        public static void main(String[] args)throws Exception{
            new client();
        }
    }
    
    

    六、叨叨叨

          这个课设的核心应该是线程,消息的格式发送和分解

          其中需要想一下的地方是自动弹出私聊那一部分。需要理清什么时候弹出私聊框,是发送方第一次向接受方发送私聊消息时,因此需要设置一个变量来标记是否是第一次发送消息。其次,因为私聊的接收方发送方的变化,需要设置两个变量来记录两方的昵称,然后根据客户自己的nickName来设置消息格式,否则的话私聊的消息格式有一方可能会变成自己发给自己的,这样另一方就接收不到对方的消息,因而只能单方面发送消息。

    展开全文
  • 内含java语言结构解释和文件名乱码,以及文件下载语言
  • JavaSocket编程.pdf

    2021-10-08 00:12:58
    JavaSocket编程.pdf
  • javasocket多线程.pdf

    2021-10-08 15:35:10
    javasocket多线程.pdf
  • 总结javasocket编程.doc

    2021-09-28 08:56:26
    总结javasocket编程.doc
  • JavaSocket[借鉴].pdf

    2021-10-11 03:25:53
    JavaSocket[借鉴].pdf
  • 用Java编写的聊天室,客户端和服务端都有界面,能够完成登录、私聊、群聊、发图片、抖动等功能,资源里面有完整代码和使用说明书。
  • Flex与javasocket通讯.pdf

    2021-10-03 23:43:03
    Flex与javasocket通讯.pdf
  • java医院挂号管理系统实现了挂好不用排队一对对治疗
  • 上学时的Javaweb课实验,仅供参考,比较简单
  • JavaSocket编程[参考].pdf

    2021-10-11 03:25:57
    JavaSocket编程[参考].pdf
  • Java网络编程 基于Socket的编程
  • 多线程JavaSocket编程示例.pdf
  • 重难点之JavaSocket编程.pdf
  • JAVA股票预测代码,随机森林为基础,可适用于毕业设计等

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,625
精华内容 650
关键字:

javasocket

java 订阅