多线程+网络编程实现聊天室

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010363836/article/details/46931327

服务器:

package com.thread.socket.demo;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * 服务器
 * 创建多线程服务器
 * @author Qixuan.Chen
 * 创建时间:2015年7月3日
 */
public class MultiServer {
	
	 private List<ChannelManager> all = new ArrayList<ChannelManager>();
	
	 public static void main(String[] args) throws IOException {    
	        new MultiServer().start();

	 }
	
	 public void start() throws IOException
	    {   
	        ServerSocket server = new ServerSocket(9999);   
	        while(true)
	        {
	            Socket client = server.accept();
	            ChannelManager channel = new ChannelManager(client);
	            all.add(channel);//统一管理
	            new Thread(channel).start();//一条道路
	        }
	    }
	
	
	/**
	 * 一个内部类,
	 * 一个客户端,一条道路
	 * 1、输入流
	 * 2、输出流
	 * 3、接收数据
	 * 4、发送数据
	 */
	class ChannelManager implements Runnable{
		
		private DataInputStream dis;
        private DataOutputStream dos;
        private boolean isRunning = true;
        private String name;
		
		public void run(){
            while(isRunning)
            {
                sendOthers(receive(),false);
            }
		}
		
		//无参数构造函数
		public ChannelManager(){
			
		}
		
		//初始化
		public ChannelManager(Socket client){
			
            try {
                dis = new DataInputStream(client.getInputStream());
                dos = new DataOutputStream(client.getOutputStream());

                this.name = dis.readUTF();
                //System.out.println(this.name);
                this.send("欢迎进入聊天室");

                sendOthers(this.name+"进入了聊天室",true);            
            } catch (IOException e) {
                CloseUtil.closeAll(dos,dis);
                isRunning = false;
            }
			
		}
		
		//接收数据
        private String receive()
        {
            String msg = "";
            try {
                msg = dis.readUTF();
            } catch (IOException e) {
                CloseUtil.closeAll(dis);
                isRunning = false;
                all.remove(this);//移除自身
            }
            return msg;

        }
        
        //发送数据
        private void send(String msg)
        {
            if(null==msg||msg.equals(""))
            {
                return;
            }
            try {
                dos.writeUTF(msg);
                dos.flush();
            } catch (IOException e) {
                CloseUtil.closeAll(dos);
                isRunning = false;
                all.remove(this);//移除自身 
            }
        }
        
        
        //发送给其他客户端
        private void sendOthers(String msg,boolean sys)
        {
            //是否为私聊  约定
            if(msg.startsWith("@")&& msg.indexOf(":")>-1)
            {
                //获取name
                String name = msg.substring(1,msg.indexOf(":"));
                String contant = msg.substring(msg.indexOf(":")+1);
                for(ChannelManager other:all)
                {
                    if(other.name.equals(name))
                    {
                        other.send(this.name+"对你悄悄的说:"+contant);
                    }
                }
            }
            else {
                for(ChannelManager other:all)
                {
                    if(other ==this)
                    {
                        continue;
                    }

                    if(sys==true)//系统信息
                    {
                        other.send("系统信息:"+msg);
                    }
                    else {
                        //发送其它客户端
                        other.send(this.name+"对所有人说"+msg);
                    }

                }
            }
            /*
            //遍历容器
            for(MyChannel others:all)
            {
                if(others == this)
                {
                    continue;
                }
                //发送给其他客户端
                others.send(msg);
            }*/

        }
		
		
	}//内部类:END
	
	

}
发送数据处理类:

package com.thread.socket.demo;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 发送数据线程,用于发送数据
 * 发送信息(供客服端使用)
 * @author Qixuan.Chen
 * 创建时间:2015年7月17日
 */
public class Send implements Runnable{
	
	//控制台输入流
    private BufferedReader console;
    //管道输出流
    private DataOutputStream dos;
    //控制线程标识
    private boolean isRunning = true;
    //名称
    private String name;
    
    
    
    public void run() {
        while(isRunning)
        {
            send( getMsgFromConsole());
        }
    }

    //初始化
    public Send() {
        console = new BufferedReader(new InputStreamReader(System.in)); 
    }
    
    public Send(Socket client,String name)
    {
        this();
        try {
            dos = new DataOutputStream(client.getOutputStream());
            this.name = name;
            send(this.name);
        } catch (IOException e) {
            //e.printStackTrace();
        	System.out.println(e);
        }
    }
    
    //1、从控制台接收数据
    private String getMsgFromConsole()
    {
        try {
            return console.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 1、从控制台接收数据
     * 2、发送数据
     */
    public void send(String msg)
    {

        try {
            if(null!=msg&& !msg.equals(""))
            {
                dos.writeUTF(msg);
                dos.flush();//强制刷新
            }
        } catch (IOException e) {
            //e.printStackTrace();
             isRunning = false;
             CloseUtil.closeAll(dos,console);
        }
    }
    
}

接收数据处理类:

package com.thread.socket.demo;

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

/**
 * 接收线程:用于接收数据
 * 接收信息(供客服端使用)
 * @author Qixuan.Chen
 * 创建时间:2015年7月17日
 */
public class Receive implements Runnable{
	 //管道的数据输入流
    private DataInputStream dis ;
    //线程标识
    private boolean isRunning = true;

    public Receive()    {   
    }   
    public Receive(Socket client) {
        try {
            dis = new DataInputStream(client.getInputStream());
        } catch (IOException e) {
            isRunning = false;
            CloseUtil.closeAll(dis);
            System.out.println("close");
        }
    }

    //接收数据的方法
    public String receive()
    {
        String msg = "";
        try {
            msg = dis.readUTF();
        } catch (IOException e) {
            isRunning = false;
            CloseUtil.closeAll(dis);
        }
        return msg;
    }

    public void run() {
        //线程体
        while(isRunning){
            System.out.println(receive());
        }   
    }

}

关闭流方法:

package com.thread.socket.demo;

import java.io.Closeable;
import java.io.IOException;

/**
 * 关闭流的方法
 */
public class CloseUtil {
    public static void closeAll(Closeable ... io)
    {
        for(Closeable temp:io)
        {
            if(null==temp)
            {
                try {
                    temp.close();
                } catch (IOException e) {
                	System.out.println(e);
                    e.printStackTrace();
                }
            }
        }
    }
}


客户端:

package com.thread.socket.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 客户端
 * 创建客户端:发送数据+接收数据
 * 写出数据:输出流
 * 读取数据:输入流
 * 输入流与输出流在同一个线程内 应该独立出来
 * 加入名称
 */
public class Client {
    public static void main(String[] args) throws IOException
    {
        System.out.println("请输入用户名:");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String name = br.readLine();
        if(name.equals(""))
        {
            return;
        }
        Socket client = new Socket("localhost",9999);
        new Thread(new Send(client,name)).start();//一条路径
        new Thread(new Receive(client)).start();//一条路径

    }
}


运行效果图:



猜你喜欢

转载自blog.csdn.net/u010363836/article/details/46931327