Java 基于UDP协议编写一个可以互相对话的聊天对话框

首先,我们先对普通的界面进行布局。创建两个类,一个Receiver,一个Sender。然后编写界面:

package Chat;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;

public class Receiver {
	public String info;
	private JFrame frame;
	private JPanel pane_buttom;
	private JSplitPane pane_center;

	// 显示内容的文本框,输入内容的文本框,发送内容按钮
	private JScrollPane pane_showWindow;
	private JScrollPane pane_inputWindow;
	private JTextArea area_showWindow;
	private JTextArea area_inputWindow;

	private JButton btn_send;

	private Dimension dimension;// 用于设置area_showWindow可拖拉的大小

	public Receiver() {
		frame = new JFrame();
		pane_buttom = new JPanel();
		pane_showWindow = new JScrollPane();
		pane_inputWindow = new JScrollPane();
		area_showWindow = new JTextArea();
		area_inputWindow = new JTextArea();
		pane_center = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false, pane_showWindow, pane_inputWindow);
		btn_send = new JButton("send");

		dimension = new Dimension(50, 300);

	}

	public void showFrame() throws UnsupportedFlavorException, IOException {
		initFrame();
		initChatTextArea();
		initButton();
		btn_send();
		readfile();
	}
	public void readfile() throws UnsupportedFlavorException, IOException {
		Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard()
                .getContents(null);

            if (t != null && t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                // 因为原系的剪贴板里有多种信息, 如文字, 图片, 文件等
                // 先判断开始取得的可传输的数据是不是文字, 如果是, 取得这些文字

                List<File> s = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                // 同样, 因为Transferable中的DataFlavor是多种类型的,
                // 所以传入DataFlavor这个参数, 指定要取得哪种类型的Data.
                for(File f:s)
                System.out.println(f.getAbsolutePath());
            }
	}

	public void initFrame() {
		frame.setTitle("receiver");
		int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
		int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
		frame.setBounds(width / 2, height / 2, 400, 450);
		frame.setVisible(true);
	}

	// 内容显示文本框和输入内容文本框
	private void initChatTextArea() {
		// 取得视图焦点
		pane_showWindow.getViewport().add(area_showWindow);
		pane_inputWindow.getViewport().add(area_inputWindow);
		// 将显示文本域设置为不可编辑
		area_showWindow.setEditable(false);
		// 设置显示文本域可拖拉的大小
		pane_showWindow.setMinimumSize(dimension);
		frame.add(pane_center, BorderLayout.CENTER);
	}

	// 发送文件,发送内容按钮
	public void initButton() {
		pane_buttom.add(btn_send);
		frame.add(pane_buttom, BorderLayout.SOUTH);
	}

	private void btn_send() {
		aaa();		//这是一个鼠标点击事件,当点击时可发送信息,这里我们需要将点击事件放在线程中,
						//不然会导致无限循环,函数aaa()在下面文章
	}
	public static void main(String[] args) throws UnsupportedFlavorException, IOException {
		Receiver chat = new Receiver();
		ReadFile r=new ReadFile();
		chat.showFrame();
	}
}

因为两个界面的布局一模一样,所以就不都贴上去了。接下来我们继续编写关于双发通信的代码,因为是基于UDP协议,所以,我们无需进行连接,只需写好端口号,直接一个程序发送,一个程序接收就可以。
下面的代码是Receiver类中的aaa()函数接收信息的代码:只需给出端口再将接收的信息显示在界面上:

private void aaa() {
			try {
				// jie
				DatagramSocket socketre = new DatagramSocket(8014);
				byte[] b = new byte[1024];
				DatagramPacket dp = new DatagramPacket(b, b.length);
				while (true) {
					socketre.receive(dp);
					area_showWindow.append("sender:" + new String(dp.getData(), 0, dp.getLength()) + "\r\n");
				}
			} catch (SocketException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}

sender类中的发送端口如下,这里我们需要用到线程,将发送信息的send方法写到线程中,并且把按钮的点击事件也写到这里。注意:由于发送方像接收方一样,未接收到就一直等待的方法,我们需要进行一个判断,如果输入框为空,我们就不进行传送信息。。。否则会无限给接收方发送空数据。

private void aaa() {
	try {
		DatagramSocket socket = new DatagramSocket(8015);
		new Thread(new Runnable() {
			@Override
			public void run() {
				btn_send.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						info = area_inputWindow.getText();
						area_showWindow.append("sender: " + info + "\r\n");
						// pw.println(info);
						area_inputWindow.setText("");
						if (info != null) {						//判断是否为空
							byte[] b = info.getBytes();
							DatagramPacket dp;
							try {
								dp = new DatagramPacket(b, b.length, InetAddress.getByName("127.0.0.1"), 8014);
								socket.send(dp);
							} catch (UnknownHostException e1) {
								// TODO Auto-generated catch block
								e1.printStackTrace();
							} catch (IOException e1) {
								// TODO Auto-generated catch block
								e1.printStackTrace();
							}
						}

					}
				});

			}
		}).start();	
	} catch (SocketException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

这样我们就做完了一端收,另一端发的代码。。接下来只要把代码互相复制一下。将端口改成不同的,即可完成互相收发的功能。receiver类aaa()函数代码如下:

	private void aaa() {
		try {
			DatagramSocket socket = new DatagramSocket(8015);
			new Thread(new Runnable() {
				@Override
				public void run() {
					btn_send.addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							info = area_inputWindow.getText();
							area_showWindow.append("sender: " + info + "\r\n");
							// pw.println(info);
							area_inputWindow.setText("");
							if (info != null) {
								byte[] b = info.getBytes();
								DatagramPacket dp;
								try {
									dp = new DatagramPacket(b, b.length, InetAddress.getByName("127.0.0.1"), 8014);
									socket.send(dp);
								} catch (UnknownHostException e1) {
									// TODO Auto-generated catch block
									e1.printStackTrace();
								} catch (IOException e1) {
									// TODO Auto-generated catch block
									e1.printStackTrace();
								}
							}

						}
					});

				}
			}).start();

			................................................上述代码
			
			
		} catch (SocketException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

sender类aaa()函数代码如下:

	private void aaa() {
		.......................................上述代码

			try {
				// jie
				DatagramSocket socketse = new DatagramSocket(8016);
				byte[] b = new byte[1024];
				DatagramPacket dp = new DatagramPacket(b, b.length);
				while(true) {
					socketse.receive(dp);
					area_showWindow.append("receiver:" + new String(dp.getData(), 0, dp.getLength()) + "\r\n");
				}
				
			} catch (SocketException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		.......................................上述代码
	}

编写完后运行效果:
Java 基于UDP协议编写一个可以互相对话的聊天对话框