java socket 即时通讯软件

接小项目,课程设计、毕业设计、微信小程序、web应用都可以(本人大厂互联网企业软件开发工程师,可验证),有需要联系qq:3524227028

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

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

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

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

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

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

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

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

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

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

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

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

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

 

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

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

数据库表设计:

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;

        }
}

 

下面是效果截图:

 

 

 

 

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

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

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值