【Java】实现简单的通信软件C/S(聊天、文件)

概述

使用swing搭建客户端界面;
image.png
界面源代码,绑定按钮监听响应操作,登录、聊天、文件传输。

import com.client.Client;
import com.client.SendFile;
import com.message.Message;

import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;

public class LoginFrame extends JFrame {
    //登陆控件
    JTextField txtUserField;
    JTextField txtPwdfField;
    JButton btnLogin;
    JButton btnReg;
    //好友区控件
    JList list;
    DefaultListModel model;
    //消息区控件
    JTextArea txtHistory = new JTextArea();
    JTextArea txtSend = new JTextArea();
    JButton btnSend = new JButton();
    //发送文件控件
    JTextField txtSendFile = new JTextField();
    JButton btnSendFile = new JButton();
    JProgressBar progressBar = new JProgressBar();
    JLabel labSendFile = new JLabel();
    private static LoginFrame frame;

    public static LoginFrame getLoginFrame() {
        if (frame == null) {
            frame = new LoginFrame();
        }
        return frame;
    }

    private LoginFrame() {
        System.out.println(Thread.currentThread().getName());
        // TODO Auto-generated constructor stub
        txtUserField = new JTextField();
        txtPwdfField = new JTextField();
        btnLogin = new JButton();
        btnLogin.setText("登录");

        btnReg = new JButton();
        btnReg.setText("注册");

        //左侧登录块
        this.setLayout(null);
        this.add(txtUserField);
        txtUserField.setBounds(10, 10, 100, 30);
        this.add(txtPwdfField);
        txtPwdfField.setBounds(10, 50, 100, 30);
        this.add(btnLogin);
        btnLogin.setBounds(10, 90, 100, 30);
        btnReg.setBounds(10, 130, 100, 30);
        this.add(btnReg);

        // JList是一个view,要添加数据,就是添加到model
        model = new DefaultListModel();// Model
        list = new JList(model);// View
        this.add(list);
        list.setBounds(120, 10, 100, 420);

        //消息块
        txtHistory.setBounds(240, 10, 300, 200);
        this.add(txtHistory);
        txtSend.setBounds(240, 220, 300, 200);
        this.add(txtSend);
        btnSend.setBounds(460, 430, 80, 30);
        this.add(btnSend);
        btnSend.setText("发送");

        //发送文件
        txtSendFile.setBounds(10, 470, 300, 30);
        this.add(txtSendFile);
        labSendFile.setText("发送文件");
        labSendFile.setBounds(10, 440, 80, 30);
        this.add(labSendFile);

        btnSendFile.setBounds(10, 520, 100, 30);
        btnSendFile.setText("发送文件");
        this.add(btnSendFile);

        //进度条
        progressBar.setBounds(320, 470, 200, 30);
        this.add(progressBar);
        progressBar.setMaximum(100);
        progressBar.setValue(0);

        //窗口布局
        setSize(600, 700);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        txtUserField.setText("QQ号");
        txtPwdfField.setText("密码");

        //登录的监听事件
        btnLogin.addMouseListener(new MouseAdapter(){
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                String msg= Message.requestLogin(txtUserField.getText(),txtPwdfField.getText());
                Client.getClient().send(msg);
            }
        });

        //发送消息监听事件
        btnSend.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                String msg=Message.requestMessage(txtUserField.getText(),list.getSelectedValue().toString(),txtSend.getText());
		//txtUserField.getText()拿到发送用户
		//list.getSelectedValue().toString()拿到选择的好友
		//txtSend.getText()聊天框信息
                Client.getClient().send(msg);
            }
        });

        //发送文件监听事件
        btnSendFile.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                //文件选择器
                JFileChooser chooser=new JFileChooser();
                chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);//文件名和文件
                //返回一个int值,分别是 JFileChooser.APPROVE_OPTION,
                // JFileChooser.CANCEL_OPTION和JFileChooser.ERROR_OPTION。
                // 在获取用户选择的文件之前,通常先验证返回值是否为APPROVE_OPTION.
                int num=chooser.showOpenDialog(null);
                //若选择了文件,则打印选择了什么文件
                if(num==JFileChooser.APPROVE_OPTION)
                {
                    File file=chooser.getSelectedFile();//获取文件
		    //开启单独的文件传输线程,处理并发。使用新的端口传输文件
                    String msg=Message.requestSendFile(txtUserField.getText(),list.getSelectedValue().toString(),file.getName(),file.length(),"127.0.0.1",10001);
                    Client.getClient().send(msg);
                    new Thread(new SendFile(file,10001)).start();
                }
            }
        });

    }

    public JTextField getTxtUserField() {
        return txtUserField;
    }

    public void setTxtUserField(JTextField txtUserField) {
        this.txtUserField = txtUserField;
    }

    public JTextField getTxtPwdField() {
        return txtPwdfField;
    }

    public void setTxtPwdField(JTextField txtPwdfField) {
        this.txtPwdfField = txtPwdfField;
    }

    public JButton getBtnLogin() {
        return btnLogin;
    }

    public void setBtnLogin(JButton btnLogin) {
        this.btnLogin = btnLogin;
    }

    public JButton getBtnReg() {
        return btnReg;
    }

    public void setBtnReg(JButton btnReg) {
        this.btnReg = btnReg;
    }

    public JTextField getTxtPwdfField() {
        return txtPwdfField;
    }

    public void setTxtPwdfField(JTextField txtPwdfField) {
        this.txtPwdfField = txtPwdfField;
    }

    public DefaultListModel getModel() {
        return model;
    }

    public void setModel(DefaultListModel model) {
        this.model = model;
    }

    public JTextArea getTxtHistory() {
        return txtHistory;
    }

    public void setTxtHistory(JTextArea txtHistory) {
        this.txtHistory = txtHistory;
    }

    public JTextArea getTxtSend() {
        return txtSend;
    }

    public void setTxtSend(JTextArea txtSend) {
        this.txtSend = txtSend;
    }

    public JTextField getTxtSendFile() {
        return txtSendFile;
    }

    public void setTxtSendFile(JTextField txtSendFile) {
        this.txtSendFile = txtSendFile;
    }

    public JButton getBtnSendFile() {
        return btnSendFile;
    }

    public void setBtnSendFile(JButton btnSendFile) {
        this.btnSendFile = btnSendFile;
    }

    public JProgressBar getProgressBar() {
        return progressBar;
    }

    public void setProgressBar(JProgressBar progressBar) {
        this.progressBar = progressBar;
    }

    public JLabel getLabSendFile() {
        return labSendFile;
    }

    public void setLabSendFile(JLabel labSendFile) {
        this.labSendFile = labSendFile;
    }
}

核心需要两个终端(客户端Client类、服务端Server类),四个线程类(客户端线程类ClientHandler,客户端接收文件线程类RecvFile、客户端发送文件线程类SendFile、服务端线程类ServerHandler),用于处理并发情况,解决同时访问与接收数据。

客户端通过传输字符串组合成不同请求

public class Message {
    public static final String LOGIN="LOGIN";//登陆消息的类型
    public static final String SPLIT="&&";//分隔符
    public static final String SUC="SUC";//成功
    public static final String FAIL="FAIL";//失败
    public static final String RELOGIN="RELOGIN";//重复登陆
    public static final String FRIENDS="FRIENDS";//好友
    public static final String CHAT="CHAT";//聊天
    public static final String FILE="FILE";//文件
    //登录消息验证
    //LOGIN&&10001&&123456
    public static String requestLogin(String userId, String userPassword)
    {
        String msg=LOGIN+SPLIT+userId+SPLIT+userPassword;
        return msg;
    }
    //获取好友列表请求
    public static String requestFriends(String userId)
    {
        String msg=FRIENDS+SPLIT+userId;
        return msg;
    }
    //发送信息请求
    public static String requestMessage(String userId,String friendId,String chatMessage)
    {
        String msg=CHAT+SPLIT+userId+SPLIT+friendId+SPLIT+chatMessage;
        return msg;
    }
    //发送文件请求
    public static String requestSendFile(String userId,String friendId,String filePath,long fileSize,String ip,int port)
    {
        String msg=FILE+SPLIT+userId+SPLIT+friendId+SPLIT+filePath+SPLIT+new Long(fileSize).toString()+SPLIT+ip+SPLIT+new Integer(port).toString();
        return msg;
    }
}

服务端同样采用字符串组合成不同的响应返回给客户端

import com.bean.User;

import java.util.ArrayList;

public class Message {
    public static final String LOGIN="LOGIN";//登陆消息的类型
    public static final String SPLIT="&&";//分隔符
    public static final String SUC="SUC";//成功
    public static final String FAIL="FAIL";//失败
    public static final String FRIENDS="FRIENDS";
    public static final String RELOGIN="RELOGIN";//重复登陆
    public static final String CHAT="CHAT";//聊天
    public static final String FILE="FILE";//文件
    //响应客户端登陆
    public static String resPoneLogin(String result){
        String msg = LOGIN+SPLIT+result;
        return msg;
    }
    //响应客户端好友请求
    public static String resPoneFriends(ArrayList<User> friendsLIst)
    {
        // FRIENDS&&好友1&&好友2
        String msg=FRIENDS;
        for (User user:friendsLIst) {
            msg+=SPLIT+user.getUserId();
        }
        return msg;
    }

}

这个小软件使用的是本地IP:127.0.0.1,也可以使用别人的IP地址,要注意统一修改。

客户端

可以向服务端发送请求,也可以接受服务端的数据;
实现代码

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;

//客户端
public class Client {
    private Socket socket;
    private static Client client;
    private static PrintWriter writer;
    //单例模式
    public static Client getClient() {
        if (client == null)
        {
            client=new Client();
        }
        return client;
    }

    public Client()
    {
        try {
	    //创建socket对象,指定IP地址以及端口号
            socket=new Socket("127.0.0.1",10086);
            //取出socket对象的输出流:socket.getOuputStream();
            writer=new PrintWriter(socket.getOutputStream());
            //启动监听线程
            new Thread(new ClientHandler(socket)).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //发送各类请求
    public static void send(String msg)
    {
        //使用该输出流写内容,该内容可以被服务端的输入流获取
        writer.println(msg);
        writer.flush();
    }
}

客户端线程类处理各类响应
实现代码:

import com.message.Message;
import com.ui.LoginFrame;

import javax.swing.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ClientHandler implements Runnable {
    private Socket socket;
    private BufferedReader reader;
    private PrintWriter writer;
    public ClientHandler(Socket socket) {
        this.socket=socket;
        try {
            reader=new BufferedReader((new InputStreamReader(socket.getInputStream())));
            writer=new PrintWriter(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        boolean isOnline=true;
        while (isOnline)
        {
            //接收服务器的信息
            try {
                String msg=reader.readLine();
                String[] data=msg.split(Message.SPLIT);
                if(data[0].equals(Message.LOGIN))
                {
                    login(data);
                }else if(data[0].equals(Message.FRIENDS))
                {
                    getFriends(data);
                }else if(data[0].equals(Message.CHAT))
                {
                    getChatMsg(data);
                }else if(data[0].equals(Message.FILE))
                {
                    getFile(data);
                }
            } catch (IOException e) {
                e.printStackTrace();
                isOnline=false;
            }
        }
    }

    private void getFile(String[] data) {
        //System.out.println(data);
        //开启线程接收文件
        new Thread(new RecvFile(data[5],data[6],data[3],data[4])).start();
    }

    //接收聊天消息
    private void getChatMsg(String[] data) {
        Date nowDate=new Date();
        DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStr=dateFormat.format(nowDate);
        String chatMsg=timeStr+" "+data[1]+" 说:\n"+data[3]+"\n";
        LoginFrame.getLoginFrame().getTxtHistory().append(chatMsg);
    }

    //得到好友列表
    private void getFriends(String[] data) {
        //事件分发线程
        SwingUtilities.invokeLater((new Runnable() {
            @Override
            public void run() {
                //清空好友列表
                LoginFrame.getLoginFrame().getModel().clear();
                //添加显示
                LoginFrame.getLoginFrame().getModel().addElement("我的好友");
                for (int i=1;i<data.length;i++)
                {
                LoginFrame.getLoginFrame().getModel().addElement(data[i]);//添加好友信息到界面
                }
            }
        }));
    }

    //得到登录信息
    private void login(String[] data) {
        if(data[1].equals(Message.SUC))
        {
            JOptionPane.showMessageDialog(null,"登录成功");
            String msg=Message.requestFriends(LoginFrame.getLoginFrame().getTxtUserField().getText());
            writer.println(msg);
            writer.flush();
        }else if(data[1].equals(Message.RELOGIN))
        {
            JOptionPane.showMessageDialog(null,"重复登录");
        }
        else {
            JOptionPane.showMessageDialog(null,"登录失败");
        }
    }
}

客户端处理文件传输线程类
发送文件实现代码I/O读取传输:

import com.ui.LoginFrame;

import javax.swing.*;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class SendFile implements Runnable {
    private File file;
    private int port;
    private ServerSocket serverSocket;
    private Socket socket;
    private FileInputStream fileInputStream;
    private BufferedOutputStream bufferedOutputStream;
    public SendFile(File file, int port) {
        this.file = file;
        this.port = port;
    }

    @Override
    public void run() {
        LoginFrame.getLoginFrame().getProgressBar().setMaximum((int) file.length());
        try {
            serverSocket=new ServerSocket(port);
            socket=serverSocket.accept();
            fileInputStream=new FileInputStream(file);
            bufferedOutputStream=new BufferedOutputStream(socket.getOutputStream());
            byte[] data=new byte[1024];
            int num=0;
            while (true)
            {
                int length=fileInputStream.read();
                if(length<0)
                {
                    break;
                }
                num+=length;
                LoginFrame.getLoginFrame().getProgressBar().setValue(num);
                bufferedOutputStream.write(data,0,length);
                bufferedOutputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            JOptionPane.showMessageDialog(null,"文件传输成功");
            try {
                if (fileInputStream==null)
                {
                    fileInputStream.close();
                }
                if (bufferedOutputStream==null)
                {
                    bufferedOutputStream.close();
                }
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

接收实现代码:

import com.ui.LoginFrame;

import javax.swing.*;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;

public class RecvFile implements Runnable {
    private String ip;
    private int port;
    private String fileName;
    private String fileSize;
    private Socket socket;
    private FileOutputStream fileOutputStream;
    private BufferedInputStream bufferedInputStream;

    public RecvFile(String ip, String port, String fileName, String fileSize) {
        this.ip = ip;
        this.port = Integer.valueOf(port);
        this.fileName = fileName;
        this.fileSize = fileSize;
    }

    @Override
    public void run() {
        LoginFrame.getLoginFrame().getProgressBar().setMaximum(Integer.parseInt(fileSize));
        try {
            socket=new Socket(ip,port);
            //存储到本地的路径加文件名
            fileOutputStream=new FileOutputStream("I:/VBlog/QQ/QQClient/temp/"+fileName);
            //字符流
            bufferedInputStream=new BufferedInputStream(socket.getInputStream());
            byte[]data=new byte[1024];
            int num=0;
            while (true)
            {
                int length=bufferedInputStream.read();
                if(length<0)
                {
                    break;
                }
                num+=length;
                LoginFrame.getLoginFrame().getProgressBar().setValue(num);
                //存入本地
                fileOutputStream.write(data,0,length);
                fileOutputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            JOptionPane.showMessageDialog(null,"文件接收成功");
            try {
                if(fileOutputStream==null) {
                    fileOutputStream.close();
                }
                if(bufferedInputStream==null) {
                    bufferedInputStream.close();
                }
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

服务端

Server类,实现与客户端socket绑定连接。使用多线程达成多个客户端同时连接,接受客户端请求的数据,自身也可以发送数据。

配置文件sqlite:
image.png
读取配置文件,获取对应的jdbc连接字符串:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class Config {
    public static String DRIVER;
    public static String URL;
    public static String DBTYPE;
    public static void init(){
        Properties properties = new Properties();
        try {
            //System.out.println(new FileInputStream("config.ini"));
            properties.load(new FileInputStream("I:\\VBlog\\QQ\\QQService\\config.ini"));
            DRIVER = properties.getProperty("DRIVER");
            URL =  properties.getProperty("URL");
            DBTYPE = properties.getProperty("DBTYPE");
            System.out.println(DBTYPE);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Dao层,获取对应数据库的操作对象:

import com.config.Config;

import java.util.HashMap;
import java.util.Map;

public class DaoFactory {
    private static Map<String, UserDao> userDaoMap = new HashMap<String, UserDao>();

    public static UserDao getUserDao(){
        if (Config.DBTYPE.equals("sqlite")) {
            return new UserDaoSqLite();
        } else if (Config.DBTYPE.equals("oracle")) {
            //return new UserDaoOracle();
        } else if (Config.DBTYPE.equals("mysql")) {
            //return new UserDaoMySql();
        }
        return null;
    }
}

实体类操作:

import com.bean.User;

import java.sql.SQLException;
import java.util.ArrayList;

public interface UserDao {
    public User login(String userId, String userPassword) throws SQLException;
    //public User register(User user);
    public ArrayList<User> friends(String user_id) throws SQLException;
}

连接数据库:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.config.Config;


public class DBConnection {
	//private static final String DRIVER = "org.sqlite.JDBC";
	//private static final String URL = "jdbc:sqlite:student.db";
	private static Connection connection;//数据库连接时静态
	public static Connection getConnection(){
		if (connection == null) {
			//数据库驱动加载
			try {
				Class.forName(Config.DRIVER);
				connection = DriverManager.getConnection(Config.URL);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return connection;
	}
}

数据库操作:

import com.bean.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

class UserDaoSqLite implements UserDao {
    @Override
    public User login(String userId, String userPassword) throws SQLException {
        Connection connection=DBConnection.getConnection();
        String sql="select * from tbl_user where user_id=? and password=?";
        PreparedStatement statement;
        statement=connection.prepareStatement(sql);
        statement.setString(1,userId);
        statement.setString(2,userPassword);
        ResultSet resultSet = statement.executeQuery();
        User user = null;
        if(resultSet.next())
        {
            user = new User();
            user.setUserId(resultSet.getString("user_id"));
            user.setUserPassword(resultSet.getString("password"));
            return user;
        }
        statement.close();
        resultSet.close();
       return user;
    }

    @Override
    public ArrayList<User> friends(String userId) throws SQLException {
        ArrayList<User> friendsList=new ArrayList<User>();
        Connection connection=DBConnection.getConnection();
        String sql="select * from v_friends where user_id=?";
        PreparedStatement statement=connection.prepareStatement(sql);
        statement.setString(1,userId);
        ResultSet resultSet=statement.executeQuery();
        while (true){
            //读取第一条数据
            User user=createFriendsList(resultSet);
            if(user==null)
            {
                //为空跳出循环
                break;
            }else {
                friendsList.add(user);
            }
        }
        statement.close();
        resultSet.close();
        return friendsList;
    }

    private User createFriendsList(ResultSet resultSet) throws SQLException {
        User user=null;
        if(resultSet.next())
        {
            user=new User();
            user.setUserId(resultSet.getString("friend_id"));
        }
        return user;
    }
}

服务端实现代码:

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

//服务端
public class Server {
    private ServerSocket serverSocket;
    public Server()
    {
        try {
            //初始化服务端socket并且绑定10086端口
            serverSocket=new ServerSocket(10086);
            Socket socket=null;
            //记录客户端数量
            int count=0;
            //循环监听等待客户端的连接
            while (true) {
                System.out.println("等待客户端连接");
                //创建接收接口
                socket = serverSocket.accept();
                System.out.println("客户端已连接");
                //启动监听线程
                new Thread(new ServerHandler(socket)).start();
                count++;
                System.out.println("客户端的数量:"+count);
                InetAddress address=socket.getInetAddress();
                System.out.println("当前客户端的IP:"+address.getHostAddress());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
服务端线程类

服务端线程类:帮助服务端处理读取发送数据;

ServerHandler类:

public class ServerHandler implements Runnable {
    private Socket socket;
    private BufferedReader reader;//字节流
    private PrintWriter writer;//字符流
    private String userId;
    private static Map<String,Socket> onlineMap=new HashMap<String, Socket>();//用户登录后记入在线列表

    public ServerHandler(Socket socket) {
        this.socket = socket;
        try {
            //获取输入流
            reader=new BufferedReader((new InputStreamReader(socket.getInputStream())));
            writer=new PrintWriter(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        boolean isOnline=true;
        while (isOnline) {
            try {
                //接收客户端发出的信息
                String msg=reader.readLine();
                String[] data=msg.split(Message.SPLIT);
                if(data[0].equals(Message.LOGIN))
                {
                    login(data);
                }else if(data[0].equals(Message.FRIENDS))
                {
                    getFriends(data);
                }else if(data[0].equals(Message.CHAT))
                {
                    sendChatMsg(data,msg);
                }else if(data[0].equals(Message.FILE))
                {
                    sendFile(data,msg);
                }
            } catch (IOException | SQLException e) {
                //e.printStackTrace();
                try {
                    //客户端断开的情况,缓存区为空的话,返回false
                    if(!reader.ready()){
                        System.out.println("用户已经退出");
                        synchronized (ServerHandler.class)
                        {
                            //移除用户
                            if(onlineMap.containsKey(userId))
                                onlineMap.remove(userId);
                        }
                    }
                    isOnline=false;
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }

        }
    }
    //响应发送文件请求
    private void sendFile(String[] data,String msg) throws IOException {
        Socket friendSocket=onlineMap.get(data[2]);
        if(friendSocket!=null)
        {
            PrintWriter writer=new PrintWriter(friendSocket.getOutputStream());
            writer.println(msg);
            writer.flush();
        }
    }
    //响应发送聊天消息请求
    private void sendChatMsg(String[] data,String chatMsg) throws IOException {
        Socket friendSocket=onlineMap.get(data[2]);
        if(friendSocket!=null)
        {
            PrintWriter writer=new PrintWriter(friendSocket.getOutputStream());
            writer.println(chatMsg);
            writer.flush();
        }
    }
    //获取好友列表,转发给客户端
    private void getFriends(String[] data) throws SQLException {
        ArrayList<User> friendsList=DaoFactory.getUserDao().friends(data[1]);
        String msg=Message.resPoneFriends(friendsList);
        writer.println(msg);
        writer.flush();
    }
    //登录响应
    private void login(String[] data) throws SQLException {
        User user= DaoFactory.getUserDao().login(data[1],data[2]);
        String reMsg=null;
        if(user!=null)
        {
            //线程锁
            synchronized (ServerHandler.class)
            {
                if(onlineMap.containsKey(user.getUserId()))//判断用户是否在线
                {
                    reMsg=Message.resPoneLogin(Message.RELOGIN);
                }else {
                    //记录第一次登陆
                    userId=user.getUserId();
                    onlineMap.put(userId,socket);
                    reMsg=Message.resPoneLogin(Message.SUC);
                }
            }
        }else {
            reMsg=Message.resPoneLogin(Message.FAIL);
        }
        writer.println(reMsg);
        writer.flush();
    }
}

补充工程源码:https://github.com/Kamisamakk/JavaProjects

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值