多線程實現聊天程序


客戶端 ChatClient.java:

package com.chat.client;

import java.awt.BorderLayout;
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.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 聊天程序客戶端
 * @author Tandaly
 * @date 2013-6-17 上午9:01:38
 */
public class ChatClient extends Frame
{
	
	private static final long serialVersionUID = -4776932994542738425L;
	
	private Socket socket = null;
	private DataOutputStream dos = null;
	private DataInputStream dis = null;
	private boolean bConnected = false;//是否連接上服務器 默認爲否
	private Thread connThread = new Thread(new ConnectThread());
	
	private TextField tfTxt = new TextField();//發送文本
	private TextArea taContent = new TextArea();//消息內容
	
	
	/**
	 * 連接服務
	 */
	public void connect()
	{
		try
		{
			this.socket = new Socket("127.0.0.1", 9999);
			this.bConnected = true;//連接服務器成功
			this.dos = new DataOutputStream(this.socket.getOutputStream());
			this.dis = new DataInputStream(this.socket.getInputStream());
		} catch (UnknownHostException e)
		{
			System.out.println("SYSTEM:服務器地址有誤!");
		} catch (IOException e)
		{
			System.out.println("SYSTEM:連接服務器失敗!");
		}
	}
	
	/**
	 * 關閉連接
	 */
	public void disConnect()
	{
		try
		{
			this.bConnected = false;//斷開服務器連接
			if(null != this.dos)
				this.dos.close();
			if(null != this.dis)
				this.dis.close();
			if(null != this.socket)
				this.socket.close();
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 運行窗體
	 */
	public void launchFrame()
	{
		setLocation(500, 100);//設置窗體位置
		setSize(400, 500);//設置窗體大小
		
		//添加窗體元素
		this.add(tfTxt, BorderLayout.SOUTH);//添加發送文本
		this.add(taContent, BorderLayout.NORTH);//添加消息內容
		
		pack();//去除空白
		
		//添加一個窗口監聽事件實現窗口關閉
		this.addWindowListener(new WindowAdapter()
		{
			@Override
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);//退出程序
			}
		});
		
		tfTxt.addActionListener(new tfTxtListener());//添加發送文本回車監聽
		
		setVisible(true);//設置窗體可見
		
		//connect();//連接服務器操作
		
		connThread.start();
		
		new Thread(new ReceiveMsgThread()).start();//啓動接收消息線程
	}
	
	/**
	 * 入口函數
	 * @param args
	 */
	public static void main(String[] args)
	{
		new ChatClient().launchFrame();
	}
	
	/**
	 * 發送文本監聽類
	 * @author Tandaly
	 * @date 2013-6-17 上午9:05:28
	 */
	class tfTxtListener implements ActionListener
	{
		@Override
		public void actionPerformed(ActionEvent e)
		{
			String content = taContent.getText();
			String txt = tfTxt.getText().trim();
			if(bConnected)
			{
				if(!"".equals(txt))
				{
					taContent.setText(content + "\n我 "
							+new SimpleDateFormat("hh:MM:ss").format(new Date())+"\n  " + txt);
					tfTxt.setText("");
					try
					{
						dos.writeUTF(txt);//向服務端發送消息
					} catch (IOException e1)
					{
						System.out.println("發送消息失敗,請檢查是否正確連接服務器!");
						bConnected = false;
					}
				}
			} else
			{
				taContent.setText(content + "\n系統消息  "
						+new SimpleDateFormat("hh:MM:ss").format(new Date())
						+"\n----發送消息失敗,請檢查服務器是否連接正常----");
				tfTxt.setText("");
			}
		}
		
	}
	 
	/**
	 * 接受消息線程
	 * @author Tandaly
	 * @date 2013-6-17 上午10:01:55
	 */
	private class ReceiveMsgThread implements Runnable
	{

		@Override
		public void run()
		{
			while(bConnected)
			{
				try
				{
					String receiveMsg = dis.readUTF();
					String content = taContent.getText();
					taContent.setText(content + "\n匿名 "
							+new SimpleDateFormat("hh:MM:ss").format(new Date())+"\n   " + receiveMsg);
				} catch (IOException e)
				{
					System.out.println("SYSTEM:接收消息失敗,服務器未連接");
				}
			}
		}
		
	}
	
	
	private class ConnectThread implements Runnable
	{
		@Override
		public void run()
		{
			while(!bConnected)
			{
				try
				{
					socket = new Socket("127.0.0.1", 9999);
					bConnected = true;
					dos = new DataOutputStream(socket.getOutputStream());
					dis = new DataInputStream(socket.getInputStream());
				} catch (Exception e)
				{
				}
			}
		}
		
	}
}



服務端 ChatServer.java:

package com.chat.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * 聊天程序服務端
 * @author Tandaly
 * @date 2013-6-17 上午9:13:47
 */
public class ChatServer
{

	private ServerSocket serverSocket = null;//服務socket對象
	private List<ClientThread> clients = new ArrayList<ClientThread>();//客戶端集合
	
	/**
	 * 啓動
	 */
	public void start()
	{
		try
		{
			this.serverSocket = new ServerSocket(9999);
			System.out.println("----聊天服務器啓動成功!----");
		} catch (BindException e)
		{
			System.out.println("SYSTEM ERROR:聊天服務啓動失敗,端口被佔用");
			System.exit(0);
		} catch (IOException e1)
		{
			System.out.println("SYSTEM ERROR:發生異常");
			System.exit(0);
		}
		
		try
		{
			while(true)
			{
				Socket socket = this.serverSocket.accept();
				ClientThread clientThread = new ClientThread(socket);//創建客戶端消息線程
				new Thread(clientThread).start();//啓動處理客戶端消息線程
				this.clients.add(clientThread);//把當前讀取到客戶端加入到客戶端集合中
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 入口函數
	 * @param args
	 */
	public static void main(String[] args)
	{
		new ChatServer().start();
	}
	
	/**
	 * 處理客戶端消息線程類
	 * @author Tandaly
	 * @date 2013-6-17 上午9:37:59
	 */
	private class ClientThread implements Runnable
	{
		private Socket socket;
		private DataInputStream dis;
		private DataOutputStream dos;
		
		public ClientThread(Socket socket)
		{
			this.socket = socket;
			
			try
			{
				this.dis = new DataInputStream(this.socket.getInputStream());
				this.dos = new DataOutputStream(this.socket.getOutputStream());
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		
		/**
		 * 發送消息給客戶端
		 * @param txt
		 */
		public void send(String txt)
		{
			try
			{
				this.dos.writeUTF(txt);
			} catch (IOException e)
			{
				System.out.println("SYSTEM:發送消息失敗,客戶端可能已經下線!");
			}//發送消息到客戶端
		}
		
		@Override
		public void run()
		{
			try
			{
				while(true)
				{
					String txt = this.dis.readUTF();//讀取客戶端消息
					System.out.println("消息:" + txt);
					
					//向客戶端羣發消息
					for(ClientThread client:clients)
					{
						if(this != client)
						{
							client.send(txt);
						}
					}
				}
			} catch (IOException e)
			{
				clients.remove(this);//移除當前客戶端
				try {
		            Thread.sleep(1000);
		        } catch (InterruptedException ex) {
		            ex.printStackTrace();
		        }
				Thread.currentThread().interrupt();//終止當前線程
				System.out.println("SYSTEM:線程" + Thread.currentThread().getName() + "被銷燬");
			}
		}
		
	}
}



作者:Tandaly

出處:http://blog.csdn.net/tandaly/article/details/9110995




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章