最近闲着无聊,用java socket做了一款简单的即时通讯软件,主要功能如下。

1. 采用C/S模式,使得各个用户通过服务器转发实现聊天的功能。

2. 分为两大模块:客户端模块和服务器端模块。

3. 客户端模块的主要功能:

1)登陆功能:用户可以注册,登录。

2)显示用户:将在线用户显示在列表中。

3)接收信息:能接收其他用户发出的信息。

4)发送信息:能发出用户要发出的信息。

5)私聊功能:选择用户进行私聊。

4.服务器端模块的主要功能:

1)检验登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就允许用户登陆。

2)显示在线状态:将该用户的状态发给各在线用户。

3)转发聊天信息:将消息转发给所有在线的用户。

 

数据库和jdk版本:mysql 5.0   ,jdk1.8

思路为:将服务器内置到客户端里,这样就不用中间服务器。每个人的电脑都是自己的一个服务器,服务器负责接收消息显示在客户端,客户端负责发送用户自己输入的信息给其他人。

数据库表设计:

java一对一聊天程序 java聊天软件_即时通讯软件

is_online用来判断用户是否在线,本人设计为在用户登录后将其设为1,然后查询其他用户的is_online,若为1,则在线,将其显示在客户端,点击界面刷新按钮来实时更新在线用户。在退出时,若未点击退出按钮,则默认在线。port 为用户在注册时为每个用户分配的端口,因为本人是在一台电脑上做的,不同客户必须分配不同端口才可通信。

 

下面是代码主类功能代码:

package main;
import java.awt.BorderLayout;
 import java.awt.EventQueue;import javax.swing.JFrame;
 import javax.swing.JPanel;
 import javax.swing.border.EmptyBorder;
 import javax.swing.GroupLayout;
 import javax.swing.GroupLayout.Alignment;
 import javax.swing.JTextArea;
 import javax.swing.JLabel;
 import javax.swing.LayoutStyle.ComponentPlacement;
 import java.awt.Font;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Scanner;import javax.swing.JTextField;
 import javax.swing.JButton;
 import javax.swing.JScrollBar;
 import javax.swing.JScrollPane;import java.awt.ScrollPane;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;public class Talk extends JFrame {
    private JPanel contentPane;
     private static JTextField textField;
     private static JTextArea textArea;
     private int id;
     private static String username;
     private Socket socket;
     private static Socket socket_server;
     private static ServerSocket serverSocket;
     private BufferedReader reader ;
     private static PrintWriter writer;
     private static BufferedReader reader_server ;
     private static PrintWriter writer_server;
     private static Scanner scanner = new Scanner(System.in);
     private static Scanner scanner_server = new Scanner(System.in);
     private static boolean send = false;
     private static boolean breakdown=false;
     /**
      * @wbp.nonvisual location=384,234
      */    /**
      * Launch the application.
      */
     public static void main(String[] args) {
         EventQueue.invokeLater(new Runnable() {
             public void run() {
                 try {
                     Talk frame = new Talk(2,"bb",serverSocket);
                     frame.setVisible(true);
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             }
         });
     }
         /**
      * Create the frame.
      */
     public Talk(int id,String username,ServerSocket serverSocket) {
         setTitle("聊天");
         this.id=id;
         this.username=username;
         this.serverSocket=serverSocket;
         setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
         setBounds(100, 100, 503, 500);
         contentPane = new JPanel();
         contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
         setContentPane(contentPane);
         
         
         JLabel lblNewLabel = new JLabel("聊 天 内 容");
         lblNewLabel.setBounds(177, 14, 102, 20);
         lblNewLabel.setFont(new Font("宋体", Font.PLAIN, 17));
         
         textField = new JTextField();
         textField.setBounds(37, 321, 264, 40);
         textField.setColumns(10);
         
         //boolean send = false;
         JButton btnNewButton = new JButton("发  送");
         btnNewButton.setBounds(309, 326, 102, 29);
         btnNewButton.setFont(new Font("宋体", Font.PLAIN, 17));
         btnNewButton.addActionListener(new ActionListener() {
             
             @Override
             public void actionPerformed(ActionEvent e) {
                 // TODO Auto-generated method stub
                 send=true;
             }
         });
         
         
         JButton btnNewButton_2 = new JButton("断开连接");
         btnNewButton_2.setBounds(131, 397, 111, 27);
         btnNewButton_2.addActionListener(new ActionListener() {
             
             @Override
             public void actionPerformed(ActionEvent e) {
                 // TODO Auto-generated method stub
                 breakdown=true;
             }
         });
         
         
         
         
         contentPane.setLayout(null);
         //contentPane.add(textArea);
         contentPane.add(textField);
         contentPane.add(btnNewButton);
         contentPane.add(btnNewButton_2);
         contentPane.add(lblNewLabel);
         
         JScrollPane scrollPane = new JScrollPane();
         scrollPane.setBounds(37, 48, 383, 240);
         contentPane.add(scrollPane);
         
         textArea = new JTextArea();
         scrollPane.setViewportView(textArea);        
         try {    
             runsocket();
         } catch (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         
         
         new Thread(new Runnable() {
             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 try {
                     startTheSocket1();
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
         }).start();
         
         
     }
     
     
     
 /    
     
     public void runsocket() throws IOException{
         new Thread(new Runnable() {
             @Override
             public void run() {
                 try {
                     startTheSocket();
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
             
         }).start();
         
       }

    客户端
    

//开始连接服务端
       public void startTheSocket() throws IOException{
           toConnectTheServer();//创建Socket并初始化
           openTheThreadToReceiveInfoFromServer();//开启一个新的线程来接受服务端发来的信息
           String yourMessage=" ";
           //一个循环,用于读取键盘的输入
           while(true) {
               yourMessage =textField.getText();            if(yourMessage!=null&&send) {
               textArea.append("\n"+"你说:"+yourMessage);
               writer.println(yourMessage);
               writer.flush();//记得flush清空缓冲区
               send = false;
                 if (yourMessage.equals("exit")||breakdown) {
                   disConnect();
                 }
             }
      
           }
       }
       
             //创建一个Socket来连接本机的18080端口的服务端并初始化reader和writer
       public void toConnectTheServer() throws IOException {
         int port = getPort(username);
         System.out.println("port="+port+"\n");
         socket=new Socket("127.0.0.1",port);
         textArea.append("等待链接!");
         reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
         writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
       }
       
      
       public void openTheThreadToReceiveInfoFromServer() throws IOException {
         new Thread(new Runnable() {
           @Override
           public void run() {
             try {
               printMessage();//打印从服务端收到的信息
             } catch (IOException e) {
               e.printStackTrace();
             }
           }
         }).start();
       }
      
       //循环不断读取服务端的信息
       public void printMessage() throws IOException {
           boolean flag = false;
         while (true) {
           String messageFromServer = null;
           try {
             messageFromServer = reader.readLine();//读取信息
             if(messageFromServer.equals("conn")) {
                 textArea.append("\n"+"连接成功");
                 flag=true;
             }          } catch (IOException e) {
             e.printStackTrace();
           } catch (NullPointerException e) {
      
           }
           if(messageFromServer.equals("exit")){
             disConnect();//关闭连接
           }
         }
       }
      
       //关闭各种
       public void disConnect() throws IOException {
         socket.close();
         reader.close();
         writer.close();
       }
     
 ///服务器端
       
       public static void startTheSocket1() throws IOException {
            acceptTheSocket();//接受连接并且初始化Socket,reader,writer
            openTheNewThreadToGetMessageFromClient();
            while(true) {
                if(breakdown) {
                    disConnect_server();
                    breakdown=false;
                    break;
                }
            }
            
          }
                   
          
          //接受连接并且初始化Socket,reader,writer
          private static void acceptTheSocket() throws IOException {
            socket_server=serverSocket.accept();//阻塞方法,用于接受Socket连接
            System.out.println("Some one connect me ,it is "+socket_server.getLocalSocketAddress());//打印地址
            System.out.println("It's port is "+socket_server.getPort());//打印端口号
            reader_server = new BufferedReader(new InputStreamReader(socket_server.getInputStream()));//获得输入流
            writer_server = new PrintWriter(new OutputStreamWriter(socket_server.getOutputStream()));//获得输出流
            String conn = "conn";
            writer_server.println(conn);//发送信息
            writer_server.flush();//flush方法用于清空缓冲区,注意的是如果不flush你的信息可能发不出去一直存留在缓冲区
          }
          //扫描键盘并输入数据
          private static void getYourMessage() throws IOException {             String yourMessage =textField.getText();
            checkYourMessage(yourMessage);//检查发送给客户端的信息
            if(send) {
            writer.println(yourMessage);//发送信息
            writer.flush();//flush方法用于清空缓冲区,注意的是如果不flush你的信息可能发不出去一直存留在缓冲区
            }
          }
          //用于检查是否退出
          private static void checkYourMessage(String yourMessage) throws IOException {
            //关闭各种
            if (yourMessage.equals("exit")) {
              socket_server.close();
              writer_server.close();
              reader_server.close();
              System.exit(0);
            }
          }
          //开启一个新的线程来监听客户端发来的信息
          private static void openTheNewThreadToGetMessageFromClient() throws IOException {
            //开启一个新的线程
            new Thread(new Runnable() {
              @Override
              public void run() {
                getTheMessageFromClient();
              }
            }).start();
          
          }
          //不断循环来获取客户端发来的信息
          private static void getTheMessageFromClient() {
            while(true) {
              String messageFromClient = null;
              try {
                messageFromClient = reader_server.readLine();
              } catch (IOException e) {
                e.printStackTrace();
              }
              printTheMessage(messageFromClient);//打印客户端发来的信息
            }
          }
          //打印客户端发来的信息
          private static void printTheMessage(String messageFromClient) {
            if(messageFromClient!=null)
                textArea.append("\n"+username+":"+messageFromClient);
          }
          
          private static void disConnect_server() {
              writer_server.close();
              try {
                 reader_server.close();
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
              }  
       
 ///      
     
       public int getPort(String name) {
             String driver1 = "com.mysql.jdbc.Driver";        
             String url = "jdbc:mysql://localhost:3306/socket";
             String username = "root";
             String password = "cc111";    
             Connection conn = null;
             Statement stmt = null;
             
             try{
                   Class.forName(driver1);
                   conn = DriverManager.getConnection(url, username, password);
                   System.out.println("Connected database successfully...");
                   stmt = conn.createStatement();
                   String sql = "select * from users where username = "+"\'"+name+"\'";
                   ResultSet result=null;
                   result = stmt.executeQuery(sql);
                     // 将查询返回的结果集进行遍历输出
                   while (result.next()) {
                         return Integer.valueOf(result.getString("port"));
                     }
                   
                }catch(SQLException se){
                   se.printStackTrace();
                }catch(Exception e){
                   e.printStackTrace();
                }finally{
                   try{
                      if(stmt!=null)
                         conn.close();
                   }catch(SQLException se){
                   }// do nothing
                   try{
                      if(conn!=null)
                         conn.close();
                   }catch(SQLException se){
                      se.printStackTrace();
                   }//end finally try
                }//end try
             
             return -1;        }
 }

下面是效果截图:

 

java一对一聊天程序 java聊天软件_socket_02

 

java一对一聊天程序 java聊天软件_客户端_03

 

 

上面代码仅为主聊天代码,显示在线用户等都没放上去。读者有兴趣可以自行去我的github上下载。

github整个工程代码链接:https://github.com/jiang-congcong/socket-instant_messaging