Java-在线聊天系统-线程

一、概述

1.目标:在上一个版本非线程的聊天系统中,出于要不断监听接收新client和接收client发出的信息,把accept()和DataInputStream.readUTF()分别写在了while()死循环里,由于俩方法都是阻塞性方法,所以一方阻塞,另一方永远得不到执行,所以,在上述代码中,只能监听第一个client的发送信息,新的client永远连接不上。

2.思路:

(1)把socet.accept()接收线程和DataInputStream.readUTF()的处理分开,把前者交给server端的处理,server端把接收到的clent封装到线程里,把DataInputStream.readUTF()的逻辑交给线程处理。

(2)采用异步IO

 

二、代码

1.ChatServer.java

import java.io.DataInputStream;

import java.io.EOFException;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.net.UnknownHostException;





public class ChatServer{

	

	private ServerSocket ss = null;

	private boolean started = false;

	

	public static void main(String[] args) {

		new ChatServer().start();

	}



	

	public void start(){

		

		try {

			ss = new ServerSocket(8888);

			started = true;

		} catch (IOException e1) {

			e1.printStackTrace();

		}

		

		try {

			while(started){

				//!!!!!注意accept()是阻塞性方法,当被readUTF()阻塞时它不会被执行

				Socket s = ss.accept();

System.out.println("a client connect------"+s);

				new Thread(new Client(s)).start();

			}

		} catch (EOFException e) {

			System.out.println("客户端已关闭!");

		} catch (IOException e) {

			e.printStackTrace();

		}finally{

			try {

				//if(dis != null ) dis.close();

				//if(s != null ) s.close();

				if(ss != null ) ss.close();

			} catch (Exception e) {

				e.printStackTrace();

			}

		}

	}

	

	private class Client implements Runnable{

		

		private Socket s;

		private DataInputStream dis = null;

		boolean bConnect = false;

		

		public Client(Socket s) {

			super();

			this.s = s;

			try {

				dis = new DataInputStream(s.getInputStream());

				bConnect = true;

			} catch (IOException e) {

				e.printStackTrace();

			}

		}





		@Override

		public void run() {

				try {

					while(bConnect){

					//!!!!!注意readUTF()是阻塞性方法

					System.out.println(dis.readUTF());

					}

				} catch (EOFException e) {

		            System.out.println("客户端已关闭!");

		        } 

				catch (IOException e) {

					e.printStackTrace();

				}finally{

					try {

						if(dis != null ) dis.close();

						if(s != null ) s.close();

					} catch (Exception e) {

						e.printStackTrace();

					}

				}

			}

		}

		



}

  

2.ChatClient.java

import java.awt.BorderLayout;

import java.awt.Button;

import java.awt.Frame;

import java.awt.TextArea;

import java.awt.TextField;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.KeyEvent;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.io.DataOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.net.Socket;

import java.net.UnknownHostException;





public class ChatClient extends Frame{



	private TextField tfText;

	private TextArea taContent;

//	private Button btnSend;

	private Socket socket;

	private DataOutputStream dos;

	

	public void launchFrame(){

		

		addWindowListener(new WindowAdapter() {

			 public void windowClosing(WindowEvent e) {

				 disconnect();

				 System.exit(0);

			 }

		});

		

		tfText = new TextField();

		taContent = new TextArea();

//		btnSend = new Button("发送");

//		

//		btnSend.addActionListener(new ActionListener() {

//			@Override

//			public void actionPerformed(ActionEvent e) {

//				//taContent.setText(taContent.getText()+"\n\r"+tfText.getText());

//				//tfText.setText("");

//				try {

//					DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

//					dos.writeUTF(tfText.getText());

//					dos.close();

//					socket.close();

//				} catch (IOException e1) {

//					e1.printStackTrace();

//				}

//			}

//		});

		

		tfText.addActionListener(new TFListener());

		

		add(taContent,BorderLayout.NORTH);

		add(tfText,BorderLayout.CENTER);

//		add(btnSend,BorderLayout.SOUTH);

		setLocation(300, 100);

		pack();

		setVisible(true);

		connect("localhost", 8888);

	}

	

	//当调用了此方法,会自动把成员变量给socket连接上server

	public void  connect(String address, int port){

		try {

			socket = new Socket(address, port);

			dos = new DataOutputStream(socket.getOutputStream());

		} catch (UnknownHostException e) {

			e.printStackTrace();

		} catch (IOException e) {

			e.printStackTrace();

		}

	}

	

	//退出时释放资源

	public void disconnect(){

		try {

			if(dos != null ) dos.close();

			if(socket != null ) socket.close();

		} catch (IOException e) {

			e.printStackTrace();

		}

	}

	

	class TFListener implements ActionListener{



		@Override

		public void actionPerformed(ActionEvent e) {

			taContent.setText(taContent.getText().trim()+"\n\r"+tfText.getText());

			

			try {

				dos.writeUTF(tfText.getText());

				dos.flush();

				tfText.setText("");

				//dos.close();

				//socket.close();

			} catch (IOException e1) {

				e1.printStackTrace();

			}

		}

	}

	

	public static void main(String[] args) {

		new ChatClient().launchFrame();

	}

}

  

三、运行结果

Java-在线聊天系统-线程

你可能感兴趣的:(java)