日期:2014-05-20  浏览次数:20811 次

java UDP可靠通信
我想做一个java基于的udp的通信,udp不是面向连接,但是我想自己手工对它进行校验和,可以用crc校验,有谁做过的,给我点帮助吧,谢谢

------解决方案--------------------
这个程序试一试:没有crc校验部分,你得的自己添加
不过你可以模拟crc校验,就是每次发送信息增加某些值,接收信息之前进行确认,再返回(类似TCP连接的三次握手)
我建议做模拟crc之前,先做模拟奇偶校验,主要先熟悉API文档中的Byte类和String类的操作技巧和编码问题
Java code

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import java.util.regex.*;;

public class PointToPointUDPChat {
    Frame f = new Frame("聊天室");

    Label lbRemoteIP = new Label("目标IP");// 对方IP
    Label lbRemotePort = new Label("目标端口");
    Label lbLocalSendPort = new Label("本地发送端口");
    Label lbLocalReceivePort = new Label("本地接收端口");

    TextField tfRemoteIP = new TextField(15);// 要发送数据的目标IP
    TextField tfRemotePort = new TextField(15);// 要发送数据的目标端口
    TextField tfLocalSendPort = new TextField(15);// 使用此端口发送数据
    TextField tfLocalReceivePort = new TextField(15);// 使用此端口发送数据

    String remoteIP = null;
    int remotePort = 0;
    int localSendPort = 0;
    int localReceivePort = 0;
    
    TextArea allChatContent = new TextArea();
    TextField sendChatContent = new TextField(20);

    Button connect = new Button("连接");
    Button disConnect = new Button("断开");
    Button bt = new Button("发送");
    Thread receiveThread = null;// 利用start和stop控制是否接收消息

    public PointToPointUDPChat() {
    initFrame();
    }

    public static void main(String args[]) {
    new PointToPointUDPChat();
    }

    // 外观布局,添加事件响应
    public void initFrame() {// //////

    f.setSize(400, 500);// 设置容器的大小
    f.setLayout(new BorderLayout());
    Panel p = new Panel();
    Panel p2 = new Panel();

    // 添加组件,布置布局
    p.setLayout(new GridLayout(5, 5));
    p.add(lbRemoteIP);
    p.add(tfRemoteIP);
    p.add(lbRemotePort);
    p.add(tfRemotePort);
    p.add(lbLocalSendPort);
    p.add(tfLocalSendPort);
    p.add(lbLocalReceivePort);
    p.add(tfLocalReceivePort);
    p.add(connect);
    p.add(disConnect);

    f.add("North", p);
    connect.addActionListener(new ActionListener() {// 连接按钮事件
            public void actionPerformed(ActionEvent e) {
            try {
                remoteIP = tfRemoteIP.getText();
                remotePort = Integer.parseInt(tfRemotePort
                    .getText());
                localSendPort = Integer.parseInt(tfLocalSendPort
                    .getText());
                localReceivePort = Integer
                    .parseInt(tfLocalReceivePort.getText());
            } catch (Exception exception) {
                prompt("连接信息不能为空或格式错误");
                return;
            }
            if (!checkIP(remoteIP)) {
                prompt("目标IP设置错误");
                return;
            }
            if (!checkPort(remotePort)) {
                prompt("目标端口设置错误");
                return;
            }
            if (!checkPort(localSendPort)) {
                prompt("本地发送端口设置错误");
                return;
            }
            if (!checkPort(localReceivePort)) {
                prompt("本地接收端口设置错误");
                return;
            }
            prompt("连接成功");
            tfRemoteIP.setEditable(false);
            tfRemotePort.setEditable(false);
            tfLocalReceivePort.setEditable(false);
            tfLocalSendPort.setEditable(false);
            receiveMessage();
            }
        });

    disConnect.addActionListener(new ActionListener() {// 断开按钮事件
            public void actionPerformed(ActionEvent e) {
            tfRemoteIP.setEditable(true);
            tfRemotePort.setEditable(true);
            tfLocalReceivePort.setEditable(true);
            tfLocalSendPort.setEditable(true);
            tfLocalReceivePort.setText("");
            tfLocalSendPort.setText("");
            tfRemoteIP.setText("");
            tfRemotePort.setText("");

            remoteIP = null;
            remotePort = 0;
            localSendPort = 0;
            localReceivePort = 0;
            receiveThread.stop();
            prompt("断开成功");
            }
        });

    f.add("Center", allChatContent);

    p2.setLayout(new FlowLayout());
    p2.add(bt);
    p2.add(sendChatContent);// ///p2面板添加发送按钮和要发送的内容
    f.add("South", p2);

    f.setVisible(true);// 让容器可显示
    f.setResizable(false);// 不可改变容器大小

    // 关闭窗口事件
    f.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
        f.setVisible(false);
        f.dispose();
        System.exit(0);
        }
    });

    // //////触发发送按钮事件
    bt.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
        sendMessage();
        }

    });
    // 模态显示按钮的触发事件

    // 输入文本框的触发事件
    sendChatContent.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
        sendMessage();
        }
    });

    }

    // 发送数据
    public void sendMessage() {// 
    // 定义ds
    DatagramSocket ds = null;
    try {
        ds = new DatagramSocket(localSendPort);
    } catch (SocketException e1) {
        prompt("本地发送端口已被使用");
        return;
    }
    // 设置发送信息
    String sendMessage = sendChatContent.getText().trim();
    if (sendMessage.equals("")) {
        prompt("无效信息");
        return;
    }
    byte[] buf = sendMessage.getBytes();// /////获得要发送的数据

    // 设置接收数据的远程IP地址
    InetAddress inetAddress = null;
    try {
        inetAddress = InetAddress.getByName(tfRemoteIP.getText().trim());
    } catch (UnknownHostException e) {
        prompt("非法远程IP地址");
        return;
    }

    // 发送
    DatagramPacket dp = new DatagramPacket(buf, 0, buf.length, inetAddress,
        remotePort);
    try {
        ds.send(dp);
    } catch (IOException e) {
        prompt("网络故障,发送失败");
        return;
    }
    sendChatContent.setText("");// //发送完数据,发送框重置为空

    allChatContent.append(new java.text.SimpleDateFormat(
        "yy-MM-dd HH:mm:ss").format(new Date())
        + " send to Remote("
        + dp.getAddress()
        + " "
        + dp.getPort()
        + ") :\n");
    allChatContent.append(sendMessage + "\n");
    ds.close();
    }

    // 接收数据
    class MyRunnable implements Runnable {
    byte buf[] = new byte[1024];
    DatagramSocket ds = null;
    DatagramPacket dp = null;

    public void run() {
        dp = new DatagramPacket(buf, 0, 1024);
        try {
        ds = new DatagramSocket(localReceivePort);
        } catch (SocketException e1) {
        prompt("本地接收端口已被使用");
        return;
        }
        while (true) {
        try {
            ds.receive(dp);
        } catch (IOException e) {
            ds.close();
            e.printStackTrace();
        }
        String receiveMessage = new String(dp.getData(), 0, dp
            .getLength());
        allChatContent.append(new java.text.SimpleDateFormat(
            "yy-MM-dd HH:mm:ss").format(new Date())// 
            + " from remote("
            + dp.getAddress().getHostAddress()
            + " " + dp.getPort() + ") :\n" + receiveMessage + "\n");
        sendChatContent.setCaretPosition(sendChatContent.getText()
            .length());

        }
    }

    }

    public void receiveMessage() {//    
    receiveThread = new Thread(new MyRunnable());
    receiveThread.start();
    }

    // 异常处理
    public void prompt(String promptMessage) {
    JOptionPane.showConfirmDialog(null, promptMessage, "友情提示",
        JOptionPane.WARNING_MESSAGE);
    }

    public boolean checkPort(int port) {
    return String.valueOf(port).matches("\\d+") && port > 1024
        && port <= 65535;

    }

    public boolean checkPort(String port) {
    return port.matches("\\d+") && Integer.parseInt(port) > 1024
        && Integer.parseInt(port) <= 65535;

    }

    
    public static boolean isDigit(String text) {
    return text.matches("\\d+");
    }    
  

    public boolean checkIP(String ip) {    
    java.util.regex.Matcher m = Pattern.compile(
        "(\\d{1,3}).(\\d{1,3}).(\\d{1,3}).(\\d{1,3})").matcher(ip);
    if (m.find()) {
        for (int i = 1; i <= 4; i++)
        if (Integer.parseInt(m.group(i)) < 0
            || Integer.parseInt(m.group(i)) > 255)
            return false;
        return true;
    }
    return true;
    }

}