Java network programming with TCP simulation of multi-user chat room

Java Network Programming TCP simulation using chat rooms

In recent B station along Shangxue Tang Qi high school teacher Java, the course is very good, not just the teacher talking about knowledge, more importantly, is involved in speaking ideas, recommend everyone to learn!
B Station Portal: point me into
Java on a blog a simple simulation of TCP basic steps of
this will be fully extended prior to knowledge of
multiplayer chat room feature:
1. Multiple clients can chat at the same time
2. You can customize the client to enter a user name
3. a client may be other messaging clients receive
4 to consult privately @Zhangsan: Hello Zhangsan!

First, a simple analysis of functional requirements, one point of view
1. Multiple clients must use to multi-threaded, and the client can simultaneously <&& send a message to accept the message>.
2. Create a string name of each client class, you can enter through the console.
3. A client and server communications will first build a pipeline, the pipeline we have stored in an array, when a message to other clients, who need traversing the pipeline again, through the pipeline to the customer corresponding to the end of the hair messages can be.
4. When the server receives a message sent by the client, let's dissect. Whisper format: @ Username: message content, look at character does not meet this format, in line, we extract the user name and the message content, the pipeline traversing find the user name corresponding to the pipeline only to give him a message. Whisper format does not comply, then we default to all who have made, in line with Point 3.

Server

Storage pipeline's time, taking into account multiple clients simultaneously write and read
, consider using CopyOnWriteArrayList, the bottom is an array array volatile transient statement, to achieve a separate read and write, copy-on-write a new array, complete the insertion, modified or removed after the operation assigned to the new array array.

CopyOnWriteArrayList<mxy> all=new CopyOnWriteArrayList<mxy>();   //用来存储管道们

establish connection

ServerSocket server=new ServerSocket(5655); 

I began to stop listening to accept the client's connection

while(true){
		Socket client=server.accept();		//时刻准备着客户端们!
		mxy dog=new mxy(client);
		all.add(dog); 						//容器管理所有的客户端
		new Thread(dog).start();			//实现能够同时接受、发送的多线程
	}

Send and receive multi-threaded class

 class mxy implements Runnable{

	private Socket client;
	private DataInputStream dis;
	private DataOutputStream dos;
	private String namee;
	public mxy(Socket client) throws IOException {
		// TODO Auto-generated constructor stub
		this.client=client;
		try {
			dis=new DataInputStream(client.getInputStream()); 
			dos=new DataOutputStream(client.getOutputStream());
			
			//先获取输入的用户名 用于下一步操作
			namee=dis.readUTF(); 

			//发送XX来了到别的客户端
			for(mxy other:all) {
				if(other.equals(this)) {//如果是客户端时自己的话就不重复发送了
					continue;
				}
				else {
					other.dos.writeUTF(namee+"进入了聊天室!");
				}
			 }
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//释放资源
			dis.close();
			dos.close();
			client.close();
		}
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		boolean flag=true;
		while(flag)
		{
			String datas = null;			//存储整个一条消息
			String[] siliaodata=null;		//存储私聊内容
			String[] siliaouser=null;		//存储私聊用户名
			try {
				datas = dis.readUTF();
				//System.out.println(datas.charAt(0));
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				//释放资源
				try {
					dis.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					dos.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					client.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			
			
			try {
				//开始判断是不是私聊,是的话-----------------------------------------
				if(datas.charAt(0)=='@')
				{
					siliaodata=datas.split(":");			//用spilt分割冒号
					siliaouser=siliaodata[0].split("@");	//用spilt分割@
					for(mxy other:all) {					//遍历客户端开始寻找
						if(other.namee.equals(siliaouser[1])) {	
							other.dos.writeUTF(namee+"对你说"+siliaodata[1]);//开始给私聊的客户端发送消息
						}
					}
				}
				//下面是不是的话,代表给全体发的-------------------------------------
				else {
					for(mxy other:all) {
						if(other.equals(this)) {
							continue;
						}
						else {
							other.dos.writeUTF(namee+"对所有人说"+datas);
						}
					 }
				
				}
				//--------------------------------------------------------------
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				//释放资源
				try {
					dis.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					dos.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					client.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
	}
	
}

Client
client, then the need to achieve receive and send messages using multiple threads, each client will need to enter their user name, the new class is sent when the user name is also the way to pass in first with a user name DataOutputStream first pass to the server for the client to other tips: XXX enter the chat room. Others have nothing

establish connection

Socket client=new Socket("localhost",5655);
public class Client {
	static String namee;
	static Scanner sc=new Scanner(System.in);
	public static void main(String[] args) throws Exception, IOException {
		Socket client=new Socket("localhost",5655);
		System.out.println("请输入您的名字");
		namee=sc.next();
		new Thread(new Send(client,namee)).start();	     //在Send构造器里传进去用户名
		new Thread(new Receive(client)).start();
	//	client.close();  这句该死的代码!错了一晚上,不能把客户端关掉!
	}

Send class
when sending to create the constructor, the user first name lost in, read out the server side distributed to other clients

class Send implements Runnable{
		Scanner sc=new Scanner(System.in);
		private DataOutputStream dos;
		private Socket client;
		private String namee;
		public Send(Socket client, String namee) {
			this.namee=namee;
			this.client=client;
			try {
				dos=new DataOutputStream(client.getOutputStream());
				dos.writeUTF(namee);       //先通过管道把用户名丢进去 用于提示XXX进入了聊天室
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
		@Override
		public void run() {
			// TODO Auto-generated method stub
			boolean flag=true;	
			while(flag)
			{
				String msg;
				msg=sc.next();				  //键盘读入要发送的信息
				try {
					dos.writeUTF(msg);           
					dos.flush();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					try {
						dos.close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}
		}
	}

Reception class
have nothing to say, the same as before with

 class Receive implements Runnable{
		private DataInputStream dis;
		private Socket client;
		private String namee;
		public Receive(Socket client) {
			this.client=client;
			try {
				dis=new DataInputStream(client.getInputStream());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				//释放资源
				try {
					dis.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					client.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}	
		@Override
		public void run() {
		boolean flag=true;	
		while(flag)
		{
			try {
				String res=dis.readUTF();
				System.out.println(res);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				try {
					dis.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
	}
}

Code renderings: Here Insert Picture Description
I did not put IO stream, encapsulate resource release method, it may seem a bit of a mess, in fact, the truth is the same, but also hope you forgive me!
If wrong place, welcome to correct me in the comments section!

Released three original articles · won praise 0 · Views 92

Guess you like

Origin blog.csdn.net/weixin_43416532/article/details/104137762