Java-----使用socket通信和线程实现聊天室功能

1.Server.java

package com.kennosaur.net.tcp.chat;

import java.awt.List;
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.Iterator;

/**
 * 创建服务器
 * 读取数据: 输入流
 *写出数据: 输出流
 * @author Administrator
 *
 */
public class Server {	
	private ArrayList<MyChannel> all = new ArrayList<MyChannel>();
	
	public static void main(String[] args) throws IOException {
		/*只接收一个客户端
		ServerSocket server = new ServerSocket(9999);
		Socket client = server.accept();
		
		DataInputStream dis = new DataInputStream(client.getInputStream());
		DataOutputStream dos =new DataOutputStream(client.getOutputStream());
		while (true) {
			//输入流
			String msg = dis.readUTF();
			System.out.println(msg);
			//输出流
			dos.writeUTF("服务器-->"+msg);	
			dos.flush();
		}
		*/
		
		new Server().start();
		
	}
	
	public void start() throws IOException {
		ServerSocket server = new ServerSocket(9999);
		while (true) {
			Socket client = server.accept();
			MyChannel channel = new MyChannel(client);
			all.add(channel);  //统一管理
			new Thread(channel).start();  //一条道路
		}
	}
	
	/**
	 * 一个客户端一条道路
	 * 1.输入流;
	 * 2.输出流;
	 * 3.接收数据;
	 * 4.发送数据;
	 * @author Administrator
	 *
	 */
	private class MyChannel implements Runnable {
		private DataInputStream dis;
		private DataOutputStream dos;
		private boolean isRunning = true;
		private String name;
		public MyChannel(Socket client) {
			try {
				dis = new DataInputStream(client.getInputStream());
				dos =new DataOutputStream(client.getOutputStream());
				
				this.name = dis.readUTF();
				this.send("欢迎进入聊天室");  //发送给自己
				sendOthers(this.name+"进入了聊天室",true);
			} catch (IOException e) {
				isRunning = false;
				CloseUtil.closeAll(dis,dos);
			}
		}
		/**
		 * 读取数据
		 * @return
		 */
		private String receive() {
			String msg="";
			try {
				 msg= dis.readUTF();
			} catch (IOException e) {
				isRunning = false;
				CloseUtil.closeAll(dis);
				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) {
				isRunning = false;
				CloseUtil.closeAll(dos);
				all.remove(this); //移除自身
			}
		}
		
		/**
		 * 发送给其他客户端
		 */
		private void sendOthers(String msg, boolean sys) {
			//是否为私聊
			if (msg.startsWith("@")&&msg.contains(":")) { //私聊
				//获取name
				String name = msg.substring(1,msg.indexOf(":"));
				String content = msg.substring(msg.indexOf(":")+1);
				for (MyChannel other : all) {
					if (other.name.equals(name)) {
						other.send(this.name+"对您悄悄地说:"+content);
					}
				}
			}else {
				//遍历容器
				for (MyChannel other : all) {
					if (other==this) {
						continue;
					}
					if (sys) { //系统信息
						other.send("系统信息:"+msg);
					}else {
						//发送给其他客户端
						other.send(this.name+"对所有人说:"+msg);
					}
				}
			}
		}
		
		@Override
		public void run() {
			while(isRunning) {
				//send(receive());  //发送给连接的客户端
				sendOthers(receive(),false);  //发送给其他客户端
			}
			
		}
		
	}

}

2.Client.java

package com.kennosaur.net.tcp.chat;

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

/**
 * 创建客户端: 发送数据+接收数据
 * 写出数据: 输出流
 * 读取数据: 输入流
 * 
 * 输入流与输出流在同一个线程内, 应该独立出来   ,彼此独立
 * @author Administrator
 *
 */
public class Client {

	public static void main(String[] args) throws UnknownHostException, IOException {
//		Socket client = new Socket("localhost", 9999);
		//控制台输入流
//		BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
//		DataOutputStream dos =new DataOutputStream(client.getOutputStream());
	
//		DataInputStream dis = new DataInputStream(client.getInputStream());
//		while (true) {
//			String info = console.readLine();
//			//输出流
//			dos.writeUTF(info);	
//			dos.flush();
			
			
			//输入流
//			String msg = dis.readUTF();
//			System.out.println(msg);
//		}
		
		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(); //一条接收路径
		
	}

}

3.客户端Send.java

package com.kennosaur.net.tcp.chat;

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

/**
 * 发送数据  线程
 * @author Administrator
 *
 */
public class Send implements Runnable{
	//控制台输入流
	private BufferedReader console ;
	//管道输出流
	private DataOutputStream dos;
	//控制线程标识
	private boolean isRunning = true;
	//名称
	private String name;
	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) {
			// TODO Auto-generated catch block
			isRunning = false;
			CloseUtil.closeAll(dos,console);
		}
		
	}
	
	//1.从控制台接收数据
	private String getMsgFromConsole() {
		try {
			return console.readLine();
		} catch (IOException e) {
			
		}
		return "";
	}
	/**
	 *1.从控制台接收数据
	 *2.发送数据
	 */
	public void send(String msg) {		
		if(null!=msg&&!msg.equals("")) {
			try {
				dos.writeUTF(msg);
				dos.flush(); //强制刷新
			} catch (IOException e) {
				isRunning = false;
				CloseUtil.closeAll(dos,console);
			}
		}
	}
	@Override
	public void run() {
		//线程体
		while(isRunning) {
			send(getMsgFromConsole());
		}
		
	}

}

4.客户端Receive.java

package com.kennosaur.net.tcp.chat;

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

/**
 * 接收线程
 * @author Administrator
 *
 */
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) {
			// TODO Auto-generated catch block
			isRunning = false;
			CloseUtil.closeAll(dis);
		}
	}
	/**
	 * 接收数据
	 * @return
	 */
	public String receive() {
		String msg = "";
		try {
			msg = dis.readUTF();
		} catch (IOException e) {
			isRunning = false;
			CloseUtil.closeAll(dis);
		}
		return msg;
	}
	@Override
	public void run() {
		//线程体
		while (isRunning) {
			System.out.println(receive());			
		}
		
	}
	
}

6.关闭所有流工具类CloseUtil.java

package com.kennosaur.net.tcp.chat;

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

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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值