根据个人理解写的,轻喷。
没什么大的逻辑,直接上代码。
UDPServer.java
package mySocket;
/*
 * 服务器端
 */
import java.awt.GridLayout;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class UDPServer extends JFrame{
	static JTextArea textArea;
	JPanel panel;
	static Vector<String> list = new Vector<String>();
	public UDPServer(){
		this.setTitle("服务器端");
		this.setLocation(100,100);
		this.setSize(1100, 600);
		
		this.setLayout(null);
		this.setLayout(new GridLayout(1,2));
		textArea = new JTextArea();
		panel = new JPanel();
		
		panel.setLayout(null);
		textArea.setSize(this.getWidth()/2, this.getHeight());
		panel.setSize(this.getWidth()/2, this.getHeight());
		textArea.setEditable(false);
		this.add(new JScrollPane(textArea));
		this.add(panel);
		
		this.setResizable(false);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
    public static void main(String[] args) {
    	UDPServer UDPserver = new UDPServer();
    	textArea.append("***************************服务器已启动,"
    			+ "等待客户端的接入***************************\n");
        try {
            DatagramSocket server = new DatagramSocket(8888);
            while (true) {
            	byte[] bytes = new byte[1024];
                DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
                server.receive(packet);
                UDPServerThread st = new UDPServerThread(server,bytes,packet,UDPserver,list);
                st.start();
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
UDPClient.java
package mySocket;
/*
 * 客户端
 */
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class UDPClient extends JFrame implements ActionListener{
	static JTextArea textArea;
	String username;
	JPanel panel;
	JTextField sendTextfield;
	JButton button;
	DatagramSocket client;
	InetAddress address;
	int port;
	Date date;
	DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	String time;
	public UDPClient(String username) throws Exception{
		this.username = username;
		this.setTitle("客户端");
		this.setLocation(300,100);
		this.setSize(400, 600);
		panel = new JPanel();
		textArea = new JTextArea();
		sendTextfield = new JTextField(20);
		button = new JButton("发送");
		this.setLayout(new GridLayout(2, 1));
		panel.setLayout(null);
		textArea.setEditable(false);
		sendTextfield.setBounds(0, 0, 200, 40);
		button.setBounds(220, 0, 50, 40);
		sendTextfield.setFocusable(true);
		this.add(new JScrollPane(textArea));
		panel.add(sendTextfield);
		panel.add(button);
		this.add(panel);
button.addActionListener(this);
		this.setResizable(false);
		this.setVisible(true);
		this.addWindowListener(new WindowAdapter() {  
			public void windowClosing(WindowEvent e) {  
				date = new Date();
				time = format.format(date);
				byte[] data = ("-"+username).getBytes();
				DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
				try {
					client.send(packet);
				} catch (IOException e1) {
					e1.printStackTrace();
				} 
			}  
		});
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		client();
	}
	public void client() throws Exception{
		/*
		 * 向服务器端发送数据
		 */
		// 1.定义服务器的地址,端口号,数据
		address = InetAddress.getByName("localhost");
		port = 8888;
		date = new Date();
		time = format.format(date); 
		client = new DatagramSocket();
		byte[] data = ("用户 "+username+" 已加入(IP地址:"+address.toString()+";端口号:"+client.getLocalPort()+";时间:"+time+")").getBytes();
		// 2.创建数据报,包含了发送的信息
		DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
		// 3.创建 DatagramSocket
		
		// 4.向服务器端发送数据
		client.send(packet);
		byte[] bytes = new byte[1024];
		UDPClientThread st = new UDPClientThread(client,bytes,packet,this);
		st.start();
	}
	public void actionPerformed(ActionEvent e) {
		JButton btn = (JButton)e.getSource();
		if(btn==button){
			String sendData = sendTextfield.getText();
			sendTextfield.setText("");
			if(!sendData.equals("")){
				date = new Date();
				time = format.format(date);
				String CRCsendData = Arrays.toString(CRCCheck.getCRCByteValue(sendData.getBytes()));
				byte[] data = ("^"+CRCsendData+"*"+username+"_"+sendData).getBytes();
				DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
				try {
					client.send(packet);
					byte[] bytes = new byte[1024];
					packet = new DatagramPacket(bytes, bytes.length);
					// 2.接收服务器响应的数据
					client.receive(packet);
					// 3.读取数据
					String reply = new String(bytes, 0, packet.getLength());
					if(reply.equals("00000000")){
						textArea.append("数据发送失败,请重新发送\n");
					}else{
						String username = reply.substring(0,reply.indexOf("_"));
						String content = reply.substring(reply.indexOf("_")+1,reply.length());
						textArea.append("用户 "+username+" 说:"+content+"\n");
					}
					
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
}
UDPServerThread.java
package mySocket;
/*
 * 服务器端线程
 */
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Vector;
import javax.swing.JList;
public class UDPServerThread extends Thread {
	DatagramSocket socket;
	byte[] bytes;
	DatagramPacket packet;
	String info;
	UDPServer UDPserver;
	Vector<String> list;
	public UDPServerThread(DatagramSocket socket, byte[] bytes, DatagramPacket packet, UDPServer uDPserver, Vector<String> list) {
		this.socket = socket;
		this.bytes = bytes;
		this.packet = packet;
		this.UDPserver = uDPserver;
		this.list = list;
	}
	public void run() {
		// 创建数据报,用于接收客户端发送的数据
		try {
			String sendData = null,username;
			boolean isresponse = false;
			// 读取数据
			info = new String(bytes, 0, packet.getLength());
			if(info.substring(0, 1).equals("-")){
				username = info.substring(1);
				list.remove(username);
				UDPserver.textArea.append("用户 "+username+" 已断开连接\n");
			}
			else if(info.substring(0, 1).equals("^")){
				isresponse = true;
				String CRCinfo = info.substring(info.indexOf("^")+1,info.indexOf("*"));
				String infoContent = info.substring(1).substring(info.indexOf("_"),info.length()-1);
				String CRCcontent = Arrays.toString(CRCCheck.getCRCByteValue(infoContent.getBytes()));
				UDPserver.textArea.append("客户端CRC校验码:"+CRCinfo+"\n");
				UDPserver.textArea.append("服务器端CRC校验码:"+CRCcontent+"\n");
				if(CRCinfo.equals(CRCcontent)){
					UDPserver.textArea.append("匹配成功\n");
					UDPserver.textArea.append(">>>>>用户 "+info.substring(info.indexOf("*")+1,info.indexOf("_"))+" 发送了一个数据包,内容为:"+infoContent+"\n\n");
					sendData = info.substring(info.indexOf("*")+1,info.indexOf("_"))+"_"+info.substring(1).substring(info.indexOf("_"),info.length()-1);
				}else{
					UDPserver.textArea.append("匹配失败\n");
					sendData = "00000000";
				}
			}else{
				isresponse = true;
				username = info.substring(info.indexOf("户")+2, info.indexOf("已")-1);
				list.add(username);
				UDPserver.textArea.append(info+"\n");
				sendData = "欢迎 "+info.substring(info.indexOf("户")+2, info.indexOf("已")-1)+" 加入";
			}
			UDPserver.panel.removeAll();
			JList<Object> lists = new JList<Object>(list);
			lists.setBounds(0, 0, 550, 600);
			UDPserver.panel.add(lists);
			UDPserver.panel.updateUI();
			/*
			 * 响应客户端发来的消息
			 */
			// 1.定义客户端的地址,端口号,数据
			if(isresponse){
				InetAddress address = packet.getAddress();
				int port = packet.getPort();
				byte[] data = sendData.getBytes();
				// 2.创建数据报,包含响应的数据信息
				packet = new DatagramPacket(data, data.length, address, port);
				// 3.响应客户端,发送数据
				socket.send(packet);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
UDPClientThread.java
package mySocket;
/*
 * 客户端线程类
 */
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPClientThread extends Thread{
	DatagramSocket client;
	byte[] bytes;
	DatagramPacket packet;
	UDPClient udpClient;
	public UDPClientThread(DatagramSocket client, byte[] bytes, DatagramPacket packet, UDPClient udpClient){
		this.client = client;
		this.bytes = bytes;
		this.packet = packet;
		this.udpClient = udpClient;
	}
	public void run(){
		try {
			packet = new DatagramPacket(bytes, bytes.length);
			client.receive(packet);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String reply = new String(bytes, 0, packet.getLength());
		if(!reply.equals(""))
			udpClient.textArea.append(reply+"\n");
	}
}
CRCCheck.java
package mySocket;
import java.util.Arrays;
public class CRCCheck {
public static void main(String[] args) {
byte[] btm = new byte[] { 12, 13, 1, 0, 0, 1, 0, 31, -19, 0, 8,
0, 1 };
byte[] btl = CRCCheck.getCRCByteValue(btm);
System.out.println(Arrays.toString(btl));
byte[] testbyte = CRCCheck.getCRCByteValue("哈哈".getBytes());
byte[] testbyte2 = CRCCheck.getCRCByteValue("哈哈".getBytes());
System.out.println(Arrays.toString(testbyte));
System.out.println(Arrays.toString(testbyte2));
}
/**
* 入口方法
* @param bt 需要校验的字节流
* @return
*/
public static byte[] getCRCByteValue(byte[] bt){
char ch = caluCRC(bt);
return charToByte(ch);
}
public static char[] crc_tb = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084,
0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c,
0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5,
0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd,
0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6,
0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee,
0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7,
0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df,
0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840,
0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948,
0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71,
0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79,
0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22,
0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a,
0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13,
0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b,
0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c,
0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004,
0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d,
0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235,
0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e,
0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466,
0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f,
0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657,
0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8,
0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0,
0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9,
0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1,
0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa,
0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2,
0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b,
0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93,
0x3eb2, 0x0ed1, 0x1ef0
};
/**
* 获得CRC验证码
*/
public static char caluCRC(byte[] pByte) {
int len = pByte.length;
char crc;
byte da;
crc = 0x0;
int i = 0;
while (len-- != 0) {
da = (byte) (crc / 256);
crc <<= 8;
int num = da ^ pByte[i];
if (num < 0)
num += 256;
crc ^= crc_tb[num];
++i;
}
return crc;
}
/**
* char 转byte
*/
public static byte[] charToByte(char c) {
byte[] b = new byte[2];
b[0] = (byte) ((c & 0xFF00) >> 8);
b[1] = (byte) (c & 0xFF);
return b;
}
}
/*用户登录界面,服务器运行状态下执行,客户端的main方法就在这个类里*/
User.java
package mySocket;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/*
 * 用户接入窗口类
 */
public class User extends JFrame implements ActionListener{
	JPanel mainPanel;
	JLabel userLabel,tipLabel;
	JTextField userTextfield;
	JButton loginBtn;
	public User(){
		this.setTitle("用户登录");
		this.setLocation(300,100);
		this.setSize(550, 600);
		
		mainPanel = new JPanel();
		userLabel = new JLabel("YourName:");
		tipLabel = new JLabel("");
		userTextfield = new JTextField(10);
		loginBtn = new JButton("登入");
		
		mainPanel.setBounds(0, 0, this.getWidth(), this.getHeight());
		mainPanel.setLayout(null);
		userLabel.setBounds(100, 200, 100, 20);
		userTextfield.setBounds(210, 195, 150, 30);
		tipLabel.setBounds(360, 200, 150, 20);
		tipLabel.setForeground(Color.red);
		loginBtn.setBounds(150, 250, 100, 20);
		
		mainPanel.add(userLabel);
		mainPanel.add(userTextfield);
		mainPanel.add(tipLabel);
		mainPanel.add(loginBtn);
		this.add(mainPanel);
		
		loginBtn.addActionListener(this);
		
		this.setResizable(false);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	public static void main(String[] args) {
		User user = new User();
	}
	public void actionPerformed(ActionEvent e) {
		JButton btn = (JButton)e.getSource();
		if(btn==loginBtn){
			String username = userTextfield.getText();
			if(username.equals("")){
				tipLabel.setText("请输入一个名称!");
			}else{
				this.dispose();
				try {
					new UDPClient(username);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
		}
		
	}
}
原文:http://www.cnblogs.com/meng1314-shuai/p/7127462.html