TCP多線程簡單聊天系統

客戶端:
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();
				}
			}
		}
	}
}


發佈了44 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章