聊天工具小模型

  今天开始自己学习java后第一个小项目的编写——“一个小型的聊天窗口互动小模型”,从昨天晚上开始看有关内容,今天早晨继续,算是完成了最初步的一些工作...现在来做一个小小的总结:

Chat0.1版本: 仅仅是new出来一个Frame的窗口,作为Client端;
Chat0.2版本: 在此Frame窗口内添加了TextFiled和TextArea,完善了Client端窗口的搭建。
Chat0.3版本: 仅仅添加了一个匿名类完成对Client端的关闭工作。
Chat0.4版本: 完成将TextField中输入的内容,显示到TextArea中的功能。

在这里,我将这4个版本合在一起,称为MyChat0.1版本:
import java.awt.*;
import java.awt.event.*;


public class ChatClient extends Frame{
	
	TextField tfTxt = new TextField();
	TextArea taContent = new TextArea();

	public static void main(String[] args) {
		new ChatClient().launchFrame();
	}
	
	public void launchFrame() {
		setLocation(400, 300);
		setSize(300, 300);
		add(tfTxt, BorderLayout.SOUTH);
		add(taContent, BorderLayout.NORTH);
//		taContent.setBackground(Color.LIGHT_GRAY);
		pack();
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				setVisible(false);
				System.exit(-1);
			}
			
		});
		tfTxt.addActionListener(new TFListener());
		setVisible(true);
	}
	
	private class TFListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String s = tfTxt.getText().trim();
			taContent.setText(s);
			tfTxt.setText("");
		}
		
	}
}


得到结果为:

聊天工具小模型


Chat0.5版本: 增加了Server端,实现Sever端的基本功能。
Chat0.6版本: 在Clint端添加方法Connect(),实现和Server端建立联接的功能;并在实现ActionListener接口时添加代码,将Client端TextField中输入的内容在Server端输出;在Server端添加必要代码,接收Client端传来的数据。

这里,我将这两个版本合并在一起,称为MyChat0.2版本:
ChatServer.java为:
import java.io.*;
import java.net.*;
public class ChatServer {

	public static void main(String[] args) {
		try {
			ServerSocket ss = new ServerSocket(8888);
			while (true) {
				Socket s = ss.accept();
System.out.println("a client connected!");
				DataInputStream dis = new DataInputStream(s.getInputStream());
				String str = dis.readUTF();
				System.out.println(str);
				dis.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


ChatClient.java为:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;


public class ChatClient extends Frame{
	
	Socket s = null;
	TextField tfTxt = new TextField();
	TextArea taContent = new TextArea();

	public static void main(String[] args) {
		new ChatClient().launchFrame();
	}
	
	public void launchFrame() {
		setLocation(400, 300);
		setSize(300, 300);
		add(tfTxt, BorderLayout.SOUTH);
		add(taContent, BorderLayout.NORTH);
//		taContent.setBackground(Color.LIGHT_GRAY);
		pack();
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				setVisible(false);
				System.exit(-1);
			}
			
		});
		tfTxt.addActionListener(new TFListener());
		setVisible(true);
		connect();
	}
	
	private void connect() {
		try {
			s = new Socket("127.0.0.1", 8888);
System.out.println("connected!");
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private class TFListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String str = tfTxt.getText().trim();
			taContent.setText(str);
			tfTxt.setText("");
			
			try {
				DataOutputStream dos = new DataOutputStream(s.getOutputStream());
				dos.writeUTF(str);
				dos.flush();
				dos.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		
	}
}


在Client窗口输入"FIRST",运行结果为:

聊天工具小模型

但是当第二次在Client窗口输入"SECOND”时,程序抛出异常,如图:

聊天工具小模型
异常显示提示:Socket已经关闭,检查程序,发现在ChatClient.java里有dos.close()语句关闭了Socket,应去掉此语句。将在MyChat0.3中改进。


Chat0.7版本同0.6,嘿嘿,貌似0.6版本改太多了。。。
Chat0.8版本: 在ChatClient.java里注释掉dos.close()语句,将DataOutputStream dos变为外部类成员变量,增加disconnect()方法;在ChatServer.java里修改while(true)语句。
在这里,我将Chat0.8版本修改的内容分开,在我的MyChat0.3版本里,实现Chat0.8版本分号前的变化。在MyChat0.4版本里,实现Chat0.8版本分号后的变化:
ChatServer.java同0.2版本,ChatClient.java为:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;


public class ChatClient extends Frame{
	
	Socket s = null;
	
	DataOutputStream dos;
	
	TextField tfTxt = new TextField();
	
	TextArea taContent = new TextArea();

	public static void main(String[] args) {
		new ChatClient().launchFrame();
	}
	
	public void launchFrame() {
		setLocation(400, 300);
		setSize(300, 300);
		add(tfTxt, BorderLayout.SOUTH);
		add(taContent, BorderLayout.NORTH);
//		taContent.setBackground(Color.LIGHT_GRAY);
		pack();
		this.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				setVisible(false);
				disconnect();
				System.exit(-1);
			}
			
		});
		tfTxt.addActionListener(new TFListener());
		setVisible(true);
		connect();
	}
	
	private void connect() {
		try {
			s = new Socket("127.0.0.1", 8888);
			dos = new DataOutputStream(s.getOutputStream());
System.out.println("connected!");
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void disconnect() {
		try {
			dos.close();
			s.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private class TFListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			String str = tfTxt.getText().trim();
			taContent.setText(str);
			tfTxt.setText("");
			
			try {
				dos.writeUTF(str);
				dos.flush();
//				dos.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		
	}
}


最后得到结果:  解决了0.2版中Client一方不能多次输入的问题,但是在Server端出现新问题,即在Client端第二次及以后输入的数据在Server端无法显示。这是因为Server端String str = dis.readUTF();为阻塞式语句,代码会一直停在那里等待read,不能回到之前代码ServerSocket ss = new ServerSocket(8888);和DataInputStream dis = new DataInputStream(s.getInputStream());MyCaht0.4版本将通过修改while(true)的方式解决这一问题。

MyChat0.4版本ChatClient.java同0.3版本,ChatServer.java代码如下:
import java.io.*;
import java.net.*;
public class ChatServer {

	public static void main(String[] args) {
		boolean started = false;
		try {
			ServerSocket ss = new ServerSocket(8888);
			started = true;
			while (started) {
				boolean bConnected = false;
				Socket s = ss.accept();
System.out.println("a client connected!");
				bConnected = true;
				DataInputStream dis = new DataInputStream(s.getInputStream());
				while (bConnected) {
				String str = dis.readUTF();
				System.out.println(str);
				}
				dis.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

得到结果如图:

聊天工具小模型
解决了之前两个版本的小BUG。
但是,当关闭窗口时,系统会抛出如下所示的异常:
java.io.EOFException
	at java.io.DataInputStream.readUnsignedShort(Unknown Source)
	at java.io.DataInputStream.readUTF(Unknown Source)
	at java.io.DataInputStream.readUTF(Unknown Source)
	at ChatServer.main(ChatServer.java:17)

这是因为
Server端String str = dis.readUTF()语句造成的!

你可能感兴趣的:(java,工作,.net,socket,dos)