开发环境:

IDEA 2018.2 集成开发工具。

实现功能:

1、用户上线,向服务器通知并注册。

2、同局域网下,所有注册用户可以进行群聊。

3、同局域网下,所有用户可与任意已注册用户进行私聊。

4、用户下线,通知服务器,服务器更新信息。

实现原理:

1、服务器端实例化一个ServerSocket对象,调用accept方法等待客户端连接到服务器。

2、客户端实例化 Socket 对象,并使用构造方法与服务器建立链接。

3、服务器端根据客户端输入信息,辨别客户端请求的功能从而做出相应响应。

实用技术:

为了能够高效的处理客户端的请求,在服务器端使用多线程处理客户端请求。并且使用 ConcurrentHashMap 来存储所有注册过的客户端。

项目源码(解释写在代码的注释当中):

服务器端:

import java.io.IOException; 
import java.io.PrintStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.Map; 
import java.util.Scanner; 
import java.util.Set; 
import java.util.concurrent.*; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
public class ManyThreadServer { 
    //存储所有注册的客户端 
    private static Map<String, Socket> clientMap = new ConcurrentHashMap<String,Socket>(); 
    //具体的处理每个客户端的请求 
    private static class ExcuteClient implements Runnable{ 
        private Socket client; 
        public ExcuteClient(Socket client) { 
            this.client = client; 
        } 
        @Override 
        public void run() { 
            try { 
                //获取客户端的输出流,读取客户端消息,并处理 
                Scanner in = new Scanner(client.getInputStream()); 
                String strFromClient; 
                while(true){ 
                    if(in.hasNextLine()){ 
                        strFromClient = in.nextLine(); 
                        //在Windows下默认换行是:\r\n,所以把\r要转换为空字符串 
                        Pattern pattern = Pattern.compile("\r"); 
                        Matcher matcher = pattern.matcher(strFromClient); 
                        strFromClient = matcher.replaceAll(""); 
                        //注册流程 
                        if(strFromClient.startsWith("useName")){ 
                            String useName = strFromClient.split("\\:")[1]; 
                            registerUser(useName,client); 
                            continue; 
                        } 
                        //群聊功能 
                        if(strFromClient.startsWith("G")){ 
                            String msg = strFromClient.split("\\:")[1]; 
                            groupChat(msg,client); 
                            continue; 
                        } 
                        //私聊功能 
                        if(strFromClient.startsWith("P")){ 
                            String userName = strFromClient.split("\\:")[1].split("-")[0]; 
                            String msg = strFromClient.split("\\:")[1].split("-")[1]; 
                            privateChat(userName,msg,client); 
                            continue; 
                        } 
                        //用户退出 
                        if(strFromClient.startsWith("B")){ 
                            String userName = null; 
                            //根据Socket找到UserName 
                            for(String keyName : clientMap.keySet()){ 
                                if(clientMap.get(keyName).equals(client)){ 
                                    userName = keyName; 
                                } 
                            } 
                            System.out.println("用户" + userName + "下线了。。。"); 
                            clientMap.remove(userName); 
                            System.out.println("当前共有用户" + clientMap.size() + "人"); 
                            continue; 
                        } 
                        else{ 
                            PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8"); 
                            out.println("输入错误。。。"); 
                        } 
                    } 
                } 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
        private void registerUser(String name,Socket client){ 
            System.out.println("用户:" + name + "已上线!"); 
            clientMap.put(name,client); 
            System.out.println("当前在线人数:" + clientMap.size() + "人!"); 
            //既然是用户在注册,所以这里服务器通知用户注册结果 
            try { 
                PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8"); 
                out.println("用户注册成功!"); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
        private void groupChat(String msg,Socket client){ 
            //取出clientMap中所有的Entry对象,遍历每个用户,并且发送消息 
            Set<Map.Entry<String,Socket>> clientSet = clientMap.entrySet(); 
            for(Map.Entry<String,Socket> entry:clientSet){ 
                try { 
                    Socket socket = entry.getValue(); 
                    //取得输出流,向客户端发送消息 
                    PrintStream out = new PrintStream(socket.getOutputStream(),true,"UTF-8"); 
                    out.println("由端口号为"+ client.getPort() + "发来的群聊消息:" + msg); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
        } 
        private void privateChat(String userName,String msg,Socket client){ 
            Socket privateSocket = clientMap.get(userName); 
            try { 
                PrintStream out = new PrintStream(privateSocket.getOutputStream(),true,"UTF-8"); 
                out.println("由端口号为:" + client.getPort() + "发来的消息:" + msg); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
    } 
    public static void main(String[] args)throws Exception{ 
        //为了提高效率,这里使用多线程进行处理 
        ExecutorService executorService = Executors.newFixedThreadPool(30); 
        //实例化ServerSocket对象,并指定IP为本地主机,端口号为6666 
        ServerSocket serverSocket = new ServerSocket(6666); 
        for(int i = 0; i < 30;i++){ 
            System.out.println("等待用户连接。。。"); 
            //等待客户端连接服务器 
            Socket client = serverSocket.accept(); 
            System.out.println("有客户端连接,端口号为:" + client.getPort()); 
            //启动线程,并处理客户端请求 
            executorService.submit(new ExcuteClient(client)); 
        } 
        //关闭线程,关闭服务器 
        executorService.shutdown(); 
        serverSocket.close(); 
    } 
}

客户端:

import java.io.IOException; 
import java.io.PrintStream; 
import java.net.Socket; 
import java.util.Scanner; 
  
/** 
 *  接收服务端发来的消息 
 */ 
class FromServer implements Runnable{ 
    Socket client; 
    public FromServer(Socket client){ 
        this.client = client; 
    } 
    @Override 
    public void run() { 
        try { 
            Scanner in = new Scanner(client.getInputStream()); 
            while (true) { 
                if (in.hasNextLine()) { 
                    System.out.println("服务器:" + in.nextLine()); 
                } 
                //判断客户端是否退出,如果推出,跳出循环,并关闭流 
                if (client.isClosed()) { 
                    System.out.println("客户端关闭。。。"); 
                    break; 
                } 
            } 
            in.close(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
} 
  
/** 
 *  向服务端发出消息 
 */ 
class ToServer  implements Runnable{ 
    Socket client; 
    public ToServer(Socket client){ 
        this.client = client; 
    } 
    @Override 
    public void run() { 
        try { 
            Scanner scanner = new Scanner(System.in); 
            PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8"); 
            while (true) { 
                System.out.println("请输入信息:"); 
                String strToserver; 
                if(scanner.hasNextLine()){ 
                    strToserver = scanner.nextLine().trim(); 
                    out.println(strToserver); 
                    //客户端退出标志:B 
                    if(strToserver.startsWith("B")){ 
                        System.out.println("客户端退出。。。"); 
                        scanner.close(); 
                        out.close(); 
                        client.close(); 
                        break; 
                    } 
                } 
            } 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
} 
public class ManyThreadClient { 
    public static void main(String[] args){ 
        try { 
            //实例化Socket对象,与服务器建立连接 
            Socket client = new Socket("127.0.0.1",6666); 
            //为了发送消息和接收消息可以同时进行,使用多线程进行处理 
            Thread thread1 = new Thread(new FromServer(client)); 
            Thread thread2 = new Thread(new ToServer(client)); 
            thread1.start(); 
            thread2.start(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
}

本文参考链接:https://www.yisu.com/zixun/696774.html
评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Java如何实现鲜花商城系统