TCP多线程简单聊天系统

本文介绍了一个简单的TCP聊天室系统的实现过程,包括客户端和服务端的代码示例。客户端能够与服务端建立连接,并通过多线程处理发送和接收消息。服务端负责接收客户端的消息并广播给其他客户端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

客户端:
package com.chen.Web.tcp.chat01;

import java.io.BufferedReader;
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 {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入这个客户端的名字");
		String name = br.readLine();
		// 创建客户端,连接本机的9999端口
		Socket client = new Socket("localhost", 9999);
		
		new Thread(new Send_Thread(client, name)).start();
		new Thread(new Receive_Thread(client)).start();
		
	}
}

服务器端:

package com.chen.Web.tcp.chat01;

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 Administrator
 *
 */
public class Server {
	
	List<MyChannel> continer = new ArrayList<MyChannel>();

	public static void main(String[] args) throws IOException {
		
		new Server().start();
	}
	
	/**
	 * 由于内部类的原因,创建一个启动方法
	 * @throws IOException
	 */
	public void start() throws IOException {
		
		// 创建服务端      ServerSocket 加服务器端口
		ServerSocket server = new ServerSocket(9999);
		// 阻塞式监听接口
		while(true) {
			
			Socket client = server.accept();
			MyChannel channel = new MyChannel(client);
			continer.add(channel);
			new Thread(channel).start();
		}
	}
	
	/**
	 * 一个客户端,一条通道
	 * @author Administrator
	 *
	 */
	private class MyChannel implements Runnable {
		
		// 输出流
		private DataInputStream is;
		// 输入流
		private DataOutputStream os;
		// 标识线程是否运转 
		private boolean isRunning = true;
		private String name;
		
		public MyChannel(Socket client) {
			
			try {
				is = new DataInputStream(client.getInputStream());
				os = new DataOutputStream(client.getOutputStream());
				this.name = is.readUTF();
				send("欢迎您进入聊天室");
				sendOthers(this.name+"进入聊天室", true);
				System.out.println(this.name+"进入聊天室");
			} catch (IOException e) {
				this.isRunning = false;
				IoUtils.closeAll(os, is);
				e.printStackTrace();
			}
		}
		
		/**
		 * 接收数据
		 * @return
		 */
		public String receive() {
			
			try {
				return is.readUTF();
			} catch (IOException e) {
				this.isRunning = false;
				IoUtils.closeAll(is);
				e.printStackTrace();
			} 
			return null;
		}

		/**
		 * 发送数据
		 * @param msg
		 */
		public void send(String msg) {
			
			try {
				
				if(msg != null && msg != "")
					os.writeUTF(msg);
			} catch (IOException e) {
				this.isRunning = false;
				IoUtils.closeAll(os);
				e.printStackTrace();
			}
		}
		
		/**
		 * 向其他客户端发送数据
		 * 1、私聊:以@开头+客户端名+msg. example:@c:你好
		 * 2、群聊
		 * @param msg
		 * @param isSysInform
		 */
		public void sendOthers(String msg, boolean isSysInform) {
			
			if(msg.startsWith("@")) {
				
				String name = msg.substring(1, msg.indexOf(":"));
				String context = msg.substring(msg.indexOf(":") + 1);
				for(MyChannel channel: continer) {
					
					if(channel.name.equals(name)) {
						
						channel.send(this.name+"悄悄对你说:"+context);
					}
				}
			}else {
				
				for(MyChannel channel: continer) {
					
					if(channel == this) {
						
						continue;
					}
					if(isSysInform) {
						
						channel.send("系统消息:"+msg);
					}else {
						
						channel.send(this.name+"对大家说:"+msg);
					}
				}
			}
		}


		@Override
		public void run() {

			while(isRunning) {
				
				sendOthers(receive(), false);
			}
		}		
	
	} 
}

发送线程:

package com.chen.Web.tcp.chat01;

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_Thread implements Runnable{
	
	// 标准输入流
	private BufferedReader console;
	// 输入流
	private DataOutputStream os;
	// 标识
	private boolean isRunning = true;
	private String name;
	

	public Send_Thread() {
		
		console = new BufferedReader(new InputStreamReader(System.in));
	}
	
	public Send_Thread(Socket client, String name) {
		
		this();
		try {
			os = new DataOutputStream(client.getOutputStream());
			this.name = name;
			send(this.name);
		} catch (IOException e) {
			this.isRunning = false;
			IoUtils.closeAll(os, console);
			e.printStackTrace();
		}
	}
	
	/**
	 * 发送数据
	 * @param msg
	 */
	public void send(String msg) {
		
	    try {
	    	if(msg != null && msg != "") {
	    		
	    		os.writeUTF(msg);
	    	}
		} catch (IOException e) {
			this.isRunning = false;
			IoUtils.closeAll(os);
			e.printStackTrace();
		}
	}
	
	/**
	 * 把标准控制台的输入转换成字符串
	 * @return String
	 */
	public String msgFromConsole() {
		
		try {
			return console.readLine();
		} catch (IOException e) {
			
			this.isRunning = false;
			IoUtils.closeAll(console);
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void run() {
		
		while(isRunning) {
			
			send(msgFromConsole());
		}
	}

}

接收线程:

package com.chen.Web.tcp.chat01;

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

/**
 * 接收线程:接收来自于socket中的字符串
 * @author Administrator
 *
 */
public class Receive_Thread implements Runnable{

	//  输出流
	private DataInputStream is;
	// 标识
	private boolean isRunning = true;
	
	public Receive_Thread() {
		
	}
	
	public Receive_Thread(Socket client) {
		
		try {
			is = new DataInputStream(client.getInputStream());
		} catch (IOException e) {
			this.isRunning = false;
			IoUtils.closeAll(is);
			e.printStackTrace();
		}
	}

	/**
	 * 接收字符串
	 * @return
	 */
	public String receive() {
		
		try {
			return is.readUTF();
		} catch (IOException e) {
			this.isRunning = false;
			IoUtils.closeAll(is);
			e.printStackTrace();
		}
		return null;
	}
	
	
	@Override
	public void run() {

		while(isRunning) {
			
			System.out.println(receive());
		}
	}
}

工具类:

package com.chen.Web.tcp.chat01;

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

/**
 * 关闭流的工具类
 * @author Administrator
 *
 */
public class IoUtils {

	public static void closeAll(Closeable ... io) {
		
		for(Closeable temp: io) {
			
			if(temp != null) {
				
				try {
					temp.close();
				} catch (IOException e) {
					
					System.out.println("关闭流出现异常");
					e.printStackTrace();
				}
			}
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值