聊天程序初级版

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

public class ChatServer {
	/**
	 * 8.2、接收多个信息,建立两个条件判断
	 */
	boolean started = false; 
	ServerSocket ss = null;
	List<Client> clients = new ArrayList<Client>();

	public static void main(String[] args) {
		new ChatServer().start();
	}	
	
	public void start() {
		/**
		 * 5、创建服务端的连接端口号ServerSocket,并接受客户端的连接accept
		 * 打印System.out.println("a client connetion")作为测试
		 */
		try{
			ss = new ServerSocket(8888);
			started = true; //创建端口后为真
		} catch (BindException e) {
			System.out.println("端口被占用");
			System.out.println("请关闭程序,重启服务器");
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			while(started){
				Socket s = ss.accept();
				System.out.println("a client connetion");
				Client c = new Client(s);
				new Thread(c).start();
				clients.add(c);
			}
		} catch (IOException e){
			e.printStackTrace();
			
		} finally {
			try {
				ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	/**
	 * 10、建立线程处理客户端
	 */	
	class Client implements Runnable{
		private Socket s;
		private DataInputStream dis = null;
		private DataOutputStream dos = null;
		private boolean bConnected = false; 
		public Client(Socket s){
			this.s = s;
			/**
			 * 7.2、建立输入流,读取客户端输入的数据
			 */
			try{
				dis = new DataInputStream(s.getInputStream());
				dos = new DataOutputStream(s.getOutputStream());
				bConnected = true;  //接收到连接后为真
			}  catch (IOException e){
				e.printStackTrace();
			}
		}
		
		/**
		 * 11、服务端接收客户端信息并发送给客户端
		 */
		public void send(String str) {
			try {
				dos.writeUTF(str);
			} catch (IOException e) {
				clients.remove(this);  //当其中一个client退出的时候要移除list里面的内容,移除当前对象的内容,用this。
				System.out.println("对方已退出!");
			}
		}
		
		@Override
		public void run() {
			try {
				while(bConnected) {
					String str = dis.readUTF();
					System.out.println(str);
					for(int i = 0;i<clients.size();i++){
						Client c = clients.get(i);
						c.send(str);
					}
					/*
					for(Iterator<Client> it = clients.iterator();it.hasNext();) {
						Client c = it.next();
						c.send(str);
					}
					
					Iterator<Client> it = clients.iterator();
					while(it.hasNext()){
						Client c =it.next();
						c.send(str);
					}
					*/
				}
			} catch (EOFException e) {
				System.out.println("client closed");
				
			} catch (IOException e){
				e.printStackTrace();
				
				/**
				 * 9、调整bug,将程序写得更健壮,打印友好提示信息
				 */
			} finally {
				try {
					if(dis != null){
						dis.close();
					}
					
					if(dos != null){
						dos.close();
					}
					
					if(s != null) {
						s.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
			
		
	}
	
	
}
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.SocketException;
import java.net.UnknownHostException;

public class ChatClient extends Frame {
	Socket s = null;  //成员变量,方便拿到socket里面的内容
	DataOutputStream dos = null;
	DataInputStream dis = null;
	private boolean bConnected = false;
	Thread tRecv = new Thread(new RecvThread());
	/**
	 * 2、添加TextField文本输入框,添加TestArea下拉条
	 */
	TextField tfTex = new TextField();
	TextArea taContent = new TextArea();
	
	public static void main(String[] args) {
		new ChatClient().luanchFrame();
	}
	
	public void luanchFrame(){
		
		/**
		 * 1、首先创建窗口
		 */
		this.setLocation(300, 400);
		this.setSize(400, 500);
		this.add(tfTex, BorderLayout.SOUTH);  //两个参数,设定传入的方向,BorderLayout区域划分为:东西南北中
		this.add(taContent, BorderLayout.EAST);
		pack();  //将区域包裹,不留空白区域
		
		/**
		 * 3、添加窗口关闭的功能,这里使用匿名类(没有名字的类)。(其它两种,并排的监听器类、内部类)
		 */
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				disconnect();  //关闭窗口的时候调用断开连接的方法
				System.exit(0);
			}
			
		});
		tfTex.addActionListener(new TFListener());
		this.setVisible(true);
		connect();
		tRecv.start();
	} 
	
	/**
	 * 6、与服务器建立连接Socket(主机,端口号)
	 *  打印一句话作为测试
	 */
	public void connect() {
		try {
			s = new Socket("127.0.0.1",8888);
			dos = new DataOutputStream(s.getOutputStream());
			dis = new DataInputStream(s.getInputStream());
			System.out.println("connect");
			bConnected = true;
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 8.1、当连接断开的时候,关闭socket
	 */
	public void disconnect() {
		try {
			bConnected = false;
			dos.close();
			dis.close();
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		/*
		try {
			bConnected = false;
			tRecv.join();
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				dos.close();
				dis.close();
				s.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		*/
	}
	
	/**
	 * 4、将输入框的内容显示到显示区域。这里使用内部类(方便修改以及添加内容,不被其它内调用)
	 */
	private class TFListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			String str = tfTex.getText().trim();  //得到输入框的内容
//			taContent.setText(str);  //显示到TextArea
			tfTex.setText("");   //将输入框的内容输出后,设置为空
			
			/**
			 * 7.1、建立输出流,向服务器端写入内容
			 *    定义为成员变量,创建对象放到连接里,连接不断开就可以一直向服务器发送信息
			 */
			try {
				dos.writeUTF(str);
				dos.flush(); //添加冲刷/刷新
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			
		}
		
		
	}

	/**
	 * 12、启用线程接收服务器发送的信息
	 */
	public class RecvThread implements Runnable {

		@Override
		public void run() {
			try{
				while(bConnected){
					String str = dis.readUTF();
//					System.out.println(str);
					taContent.setText(taContent.getText() + str +"\n");
				}
			} catch(SocketException e) {
				System.out.println("a client 已退出!");
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		
	}
}











  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值