Java基于的网络部分的微信聊天系统的模拟

首先来看一下单线程下的聊天框架,其实代码很简单,就是利用Socket和ServerSocket类的一些功能实现,但要整个深入了解聊天系统,则需要一定的TCP/IP协议相关的知识与操作系统方面的知识

服务器端:服务器端是用来接收消息并发送消息的

package mylittlemessage;;
import java.io.IOException; 
import java.io.PrintStream; 
import java.net.ServerSocket; 
import java.net.Socket;
 import java.util.Scanner;
/** * 单线程服务器端 
*/
 public class SingleServer
  {  
       public static void main(String[] args) throws Exception
       {       
            // 创建服务端Socket,端口号为6666        
        ServerSocket serverSocket = new ServerSocket(6666);     
        try {           
            System.out.println("等待客户端连接ing...");          
            // 等待客户端连接,有客户端连接后返回客户端的Socket对象,否则线程将一直阻塞    
            Socket client = serverSocket.accept();           
            System.out.println("有新的客户端连接,端口号为: "+client.getPort());   
             // 获取客户端的输入输出流          
            Scanner clientInput = new Scanner(client.getInputStream());       
            clientInput.useDelimiter("\n");         
            PrintStream clientOut = new PrintStream(client.getOutputStream(),true,"UTF-8");
            /*
            *  此处需要注意,因为是单线程所以大家都是先读在写,防止阻塞
            */           
            // 读取客户端输入         
            if (clientInput.hasNext())
            {                
                System.out.println(client.getInetAddress()+"说: "+clientInput.next());     
            } 
            // 向客户端输出           
            clientOut.println("Hello I am Server,Welcome!");      
            // 关闭输入输出流         
            clientInput.close();         
            clientOut.close();            
            serverSocket.close();
        }catch (IOException e) 
        {            
            System.err.println("服务端通信出现异常,错误为"+e);      
      }   
    } 
}

客户端,客户端就是建立连接,接受消息,并发送消息

package mylittlemessage;;
 
import java.io.IOException; 
import java.io.PrintStream; 
import java.net.Socket; 
import java.util.Scanner;
 
/** * 
单线程聊天室客户端 * 
*/ 
public class SingleClient 
{    
    public static void main(String[] args) throws Exception
    {       
        String serverName = "127.0.0.1";    
        Integer port = 6666;       
        try {        
            // 创建客户端Socket连接服务器    
            Socket client = new Socket(serverName,port);         
            System.out.println("连接上服务器,服务器地址为: "+client.getInetAddress());   
            // 获取输入输出流           
            PrintStream out = new PrintStream(client.getOutputStream(), true,"UTF-8");   
            Scanner in = new Scanner(client.getInputStream());        
            in.useDelimiter("\n");            // 向服务器输出内容         
            out.println("Hi I am Client!!");            // 读取服务器输入     
            if (in.hasNext()) 
            {              
                System.out.println("服务器发送消息为: "+in.next());    
            }            
            in.close();     
            out.close();      
            client.close();    
            }
            catch (IOException e) 
            {          
                System.err.println("客户端通信出现异常,错误为"+e);      
            } 
        }
}

多线程下的聊天系统

用来由于单线程的局限性,客户端只能一次完成一次收发,而服务器一次也只能服务一个客户,所以,有了下面的多线程聊天系统,使得聊天能够更加灵活,并实现了(注册,群聊,私发消息)等多种功能

客户端

package mylittlemessage;
 
import java.io.IOException; 
import java.io.PrintStream;
 import java.net.Socket; 
 import java.util.Scanner;
 
 
/** * 读取服务器信息线程 */
 class ReadFromServerThread implements Runnable
  {    
      private Socket client;
    public ReadFromServerThread(Socket client) 
    {        
        this.client = client;  
  }   
   @Override   
    public void run()
     {        
        try 
        {       
            // 获取客户端输入流         
            Scanner in = new Scanner(client.getInputStream());     
            in.useDelimiter("\n");            
            while (true) 
            {          
                if (in.hasNext()) 
                {     
                    System.out.println("从服务器发来的消息为: "+in.next());  
                }                
                 // 此客户端退出        
                if (client.isClosed()) 
                {         
                    System.out.println("客户端已关闭");     
                    break;       
                }   
            }   
            in.close();    
        } 
        catch (IOException e)
        {          
           System.err.println("客户端读线程异常,错误为 "+e);
        }  
    }
}
 
/** * 将信息发送给服务器线程 */ 
class WriteToServerThread implements Runnable
 {   
    private Socket client;
    public WriteToServerThread(Socket client)
    {    
        this.client = client;  
    } 
    public void run() 
    {       
         try{            
             // 获取键盘输入            
            Scanner scanner = new Scanner(System.in);            
            scanner.useDelimiter("\n");            // 获取客户端输出流            
            PrintStream out = new PrintStream(client.getOutputStream());            
            while (true) 
            {                
                System.out.println("请输入要发送的消息..");               
                String strToServer;                
                if (scanner.hasNextLine()) 
                {                    
                    strToServer = scanner.nextLine().trim(); 
                    out.println(strToServer);                  
                    // 客户端退出标志                    
                    if (strToServer.equals("byebye")) 
                    {                        
                        System.out.println("关闭客户端");                        
                        scanner.close();                        
                        out.close();                        
                        client.close();                        
                        break;                   
                    }                
                }            
            }        
            }
        catch (IOException e) 
        {           
            System.out.println("客户端写线程异常,错误为 "+e);       
        }  
    } 
}
 
/**
 * 多线程聊天室客户端 
*/ 
public class MultiThreadClient 
{    
    public static void main(String[] args) 
    {       
         try 
         {            
            Socket client = new Socket("127.0.0.1",6666); 
            // 读取服务器消息线程            
            Thread readFromServer  = new Thread(new ReadFromServerThread(client));            
            Thread writeToServer = new Thread(new WriteToServerThread(client));            
            readFromServer.start();            
            writeToServer.start();        
         } 
         catch (IOException e) 
        {            
            e.printStackTrace();        
        }   
    } 
}

服务器端

package bitekeji;
 
import java.io.IOException;
import java.io.PrintStream; 
import java.net.ServerSocket;
import java.net.Socket; 
import java.util.Iterator; 
import java.util.Map;
import java.util.Scanner; 
import java.util.Set; 
import java.util.concurrent.ConcurrentHashMap; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern;
 
/**
 * 多线程聊天室服务端 * 
 */ 
public class MultiThreadServer 
{    
    // 存储所有注册的客户端    
    private static Map clientMap = new ConcurrentHashMap();
 
    // 具体处理与每个客户端通信的内部类    
    private static class ExecuteClient implements Runnable 
    {        
        private Socket client;
 
        public ExecuteClient(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("userName")) 
                        {                           
                            String userName = strFromClient.split("\\:")[1];
                            registerUser(userName,client);                            
                            continue;                       
                        }                        
                        // 群聊流程                        
                        if (strFromClient.startsWith("G")) 
                        {                            
                            String msg = strFromClient.split("\\:")[1];                            
                            groupChat(msg);                            
                            continue;                       
                             }
                        // 私聊流程                        
                        if (strFromClient.startsWith("P")) 
                        {                            
                            String userName = strFromClient.split("\\:")[1].split("-")[0];
                            String msg = strFromClient.split("\\:")[1].split("-")[1];
                            privateChat(userName,msg);
                        }                       
                        // 用户退出                        
                        if (strFromClient.contains("byebye")) 
                        {                            
                            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);                            
                            continue;                        
                        }                    
                    }                
                }            
                }
                catch (IOException e) 
                {                
                    System.err.println("服务器通信异常,错误为 "+e);
                }        
        }        
            // 注册方法       
            private void registerUser(String userName,Socket client)
            {            
                System.out.println("用户姓名为: "+userName);            
                System.out.println("用户"+userName+"上线了!");            
                System.out.println("当前群聊人数为: "+(clientMap.size()+1)+"人");            
                // 将用户信息保存到map中            
                clientMap.put(userName,client);            
                try
                {                
                    PrintStream out  = new PrintStream(client.getOutputStream(),true,"UTF-8");
                    // 告知用户注册成功                
                    out.println("用户注册成功!");            
                } catch (IOException e) 
                {                
                    e.printStackTrace();            
                }        
                                    
            }       
            // 群聊流程        
            private void groupChat(String msg) 
            {            
                // 取出clientMap中所有Entry遍历发送群聊信息            
                Set> clientSet = clientMap.entrySet();            
                for (Map.Entry entry : clientSet)
                {                
                    try {                    
                            Socket socket = entry.getValue();                    
                            // 取得每个客户端的输出流                    
                            PrintStream out = new PrintStream(socket.getOutputStream(),true,"UTF-8");                    
                         out.println("群聊信息为: "+msg);                
                        }
                    catch (IOException e) 
                    {                    
                        System.err.println("群聊异常,错误为 "+e);                
                    }
                }       
            }        
            // 私聊流程        
            private void privateChat(String userName,String msg) 
            {            
                Socket privateSocket = clientMap.get(userName);            
                try {                
                    PrintStream out = new PrintStream(privateSocket.getOutputStream(),true,"UTF-8");                
                    out.println("私聊信息为: "+msg);            
                    }
                catch (IOException e) 
                {                
                    System.err.println("私聊异常,错误为"+e);            
                }        
            }
    }
 
    public static void main(String[] args) throws Exception
    {        
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        ServerSocket serverSocket = new ServerSocket(6666);       
        for (int i = 0 ; i < 20 ; i++) 
        {            
            System.out.println("等待客户端连接...");            
            Socket client = serverSocket.accept();            
            System.out.println("有新的客户端连接,端口号为: "+client.getPort());            
            executorService.submit(new ExecuteClient(client));        
        }        
        executorService.shutdown();        
        serverSocket.close();    
        } 
    }

 

你可能感兴趣的:(java)