多线程实现聊天程序


客户端 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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值