最近在写嵌入式通讯程序,所以就想用Java写一个Udp通讯的服务端程序来实现,从开发板上发数据包到PC,PC上的服务端程序解析数据,以前写的Java程序比较少,所以就写了一个Java的Udp的Server和Client集一体的通讯程序,现把代码列出,还有不足之处,请各位高手指点。
/*主函数 udpmain.java*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jappudp;
/**
*
* @author AlimysoYang
*/
public class udpmain {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
udpframe uf = new udpframe();
}
}
/*主窗口、实现程序 udpframe.java*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jappudp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.lang.*;
import java.util.Date;
import java.text.SimpleDateFormat;
/**
*
* @author AlimysoYang
*/
public class udpframe extends JFrame implements Runnable,ActionListener{
private Thread rthread = null;
//初始化窗口控件
private JLabel lbRecvPort = new JLabel("接收端口",JLabel.LEFT);
private JLabel lbSendIP = new JLabel("发送IP",JLabel.LEFT);
private JLabel lbSendPort = new JLabel("发送端口",JLabel.LEFT);
private JLabel lbRecv = new JLabel("接收数据",JLabel.LEFT);
private JLabel lbSend = new JLabel("发送数据",JLabel.LEFT);
private JTextField tfRecvPort = new JTextField("8800",6);
private JTextField tfSendIP = new JTextField("127.0.0.1",15);
private JTextField tfSendPort = new JTextField("8801",6);
private JTextArea taRecv = new JTextArea();
private JTextArea taSend = new JTextArea();
private JButton btnConnect = new JButton("连接");
private JButton btnDisConnect = new JButton("断开连接");
private JButton btnSend = new JButton("发送");
private JCheckBox cbHex = new JCheckBox("16进制",false);
private JPanel plTop = new JPanel(new FlowLayout(FlowLayout.LEFT));
private JPanel plBottom = new JPanel(new FlowLayout(FlowLayout.LEFT));
private JScrollPane spRecv = new JScrollPane(taRecv);
private JScrollPane spSend = new JScrollPane(taSend);
private GridBagLayout mgbLayout = new GridBagLayout();
private GridBagConstraints mgbConstraints = new GridBagConstraints();
private int sPort,rPort;
private String sHost;
private DatagramSocket sUdp = null;
private DatagramSocket rUdp = null;
private DatagramPacket sPacket,rPacket;
private byte[] sBuffer = null;
private byte[] rBuffer = null;
private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//构造函数,实现窗口布局
public udpframe()
{
InitComponents();
}
//重构线程start函数
public void start()
{
if (rthread==null)
{
rthread = new Thread(this);
rthread.start();
}
}
//重构线程stop函数
public void stop()
{
rthread = null;
}
//线程run函数,主要实现对指定端口的数据接收
public void run()
{
Thread cthread = Thread.currentThread();
while (cthread==rthread)
{
RecvData();
/*try
{
rthread.sleep(1000);
}catch(InterruptedException ie)
{
System.out.println(ie);
}*/
}
}
private void setMainLayout(int gridx,int gridy,int gridwidth,int gridheight,int weightx,int weighty,int fill)
{
mgbConstraints.gridx = gridx;
mgbConstraints.gridy = gridy;
mgbConstraints.gridwidth = gridwidth;
mgbConstraints.gridheight = gridheight;
mgbConstraints.weightx = weightx;
mgbConstraints.weighty = weighty;
mgbConstraints.fill = fill;
}
//初始化窗口布局
private void InitComponents()
{
plTop.add(lbRecvPort);
plTop.add(tfRecvPort);
plTop.add(lbSendIP);
plTop.add(tfSendIP);
plTop.add(lbSendPort);
plTop.add(tfSendPort);
plTop.add(btnConnect);
plTop.add(btnDisConnect);
plTop.add(cbHex);
this.getContentPane().setLayout(mgbLayout);
setMainLayout(0,0,1,1,100,2,GridBagConstraints.BOTH);
mgbLayout.setConstraints(plTop, mgbConstraints);
getContentPane().add(plTop);
setMainLayout(0,1,1,1,100,2,GridBagConstraints.BOTH);
mgbLayout.setConstraints(lbRecv, mgbConstraints);
getContentPane().add(lbRecv);
setMainLayout(0,2,1,1,100,46,GridBagConstraints.BOTH);
mgbLayout.setConstraints(spRecv, mgbConstraints);
getContentPane().add(spRecv);
setMainLayout(0,3,1,1,100,2,GridBagConstraints.BOTH);
mgbLayout.setConstraints(lbSend, mgbConstraints);
getContentPane().add(lbSend);
setMainLayout(0,4,1,1,100,46,GridBagConstraints.BOTH);
mgbLayout.setConstraints(spSend, mgbConstraints);
getContentPane().add(spSend);
plBottom.add(btnSend);
setMainLayout(0,5,1,1,100,2,GridBagConstraints.BOTH);
mgbLayout.setConstraints(plBottom,mgbConstraints);
getContentPane().add(plBottom);
btnDisConnect.setEnabled(false);
btnConnect.addActionListener(this);
btnDisConnect.addActionListener(this);
btnSend.addActionListener(this);
this.setTitle("UDP(for NetBeans) v1.00");
this.setSize(800,600);
this.setResizable(true);
SrceenCenter();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
//布局窗口在屏幕居中
private void SrceenCenter()
{
Toolkit tkit = Toolkit.getDefaultToolkit();
Dimension screensize = tkit.getScreenSize();
Dimension framesize = this.getSize();
this.setLocation((screensize.width - framesize.width) / 2, (screensize.height - framesize.height) / 2);
}
//发送数据
private void SendData(String Data)
{
try
{
if (sUdp==null)
sUdp = new DatagramSocket();
sHost = tfSendIP.getText().trim();
sPort = Integer.parseInt(tfSendPort.getText().trim());
sBuffer = new byte[1024];
if (cbHex.isSelected())
{
SendHexData(Data);
}
else
{
sBuffer = Data.getBytes();
}
sPacket = new DatagramPacket(sBuffer,sBuffer.length,InetAddress.getByName(sHost),sPort);
sUdp.send(sPacket);
sUdp.close();
sUdp = null;
}catch(IOException e)
{
sUdp.close();
sUdp = null;
System.out.println("数据发送错误:" + e);
}
}
//判断字符是否是16进制中的字符
private boolean CharInRange(char c)
{
boolean r = false;
if ((c>='0') && (c<='9'))
r = true;
if ((c>='a') && (c<='f'))
r = true;
if ((c>='A') && (c<='F'))
r = true;
return r;
}
//把16进制字符串转成字节
private byte StrToByte(String s)
{
/*byte rb;
int i = Integer.parseInt(s, 16);
String rs = String.valueOf(i);
rb = Integer.valueOf(String.valueOf(Integer.parseInt(s, 16))).byteValue();
return rb;*/
return Integer.valueOf(String.valueOf(Integer.parseInt(s, 16))).byteValue();
}
//发送16进制数据
private void SendHexData(String Data)
{
//sBuffer = new byte[1024];
int datalen = Data.getBytes().length;
int i = 0,j = 0;
while (i<datalen)
{
while ((i>=0) && (!CharInRange(Data.charAt(i))))
{
i++;
}
if (((i + 1)>datalen) || (!CharInRange(Data.charAt(i + 1))))
{
sBuffer[j] = StrToByte(String.valueOf(Data.charAt(i)));
j++;
}
else
{
sBuffer[j] = StrToByte(Data.substring(i, i + 2));
j++;
}
i += 2;
}
}
//接收数据
private void RecvData()
{
try
{
String recvData;
rUdp.receive(rPacket);
if (cbHex.isSelected())
recvData = RecvHexData();
else
recvData = new String(rPacket.getData()).trim();
recvData = "[" + rPacket.getAddress().getHostAddress() + ":" +
String.valueOf(rPacket.getPort()) + " // " +
df.format(new Date()) + "] " + recvData;
taRecv.append(recvData + "/n");
}catch(IOException e)
{
System.out.println(e);
}
}
//接收端连接
private void Connect()
{
try
{
rPort = Integer.parseInt(tfRecvPort.getText().trim());
if (rUdp==null)
rUdp = new DatagramSocket(rPort);
btnConnect.setEnabled(false);
btnDisConnect.setEnabled(true);
rBuffer = new byte[1024];
rPacket = new DatagramPacket(rBuffer,rBuffer.length);
start();
}catch(SocketException e)
{
DisConnect();
System.out.println("发送端连接失败:" + e);
}
}
//接收端断开
private void DisConnect()
{
if (rUdp!=null)
{
rUdp.close();
rUdp = null;
}
stop();
btnConnect.setEnabled(true);
btnDisConnect.setEnabled(false);
}
//接收16进制数据
private String RecvHexData()
{
StringBuffer sb = new StringBuffer(rBuffer.length);
String rHex = "";
int i;
for (i = 0;i<rBuffer.length;i++)
{
rHex = Integer.toHexString(rBuffer[i] & 0xFF);
if (rHex.length()==1)
rHex = '0' + rHex;
sb.append(rHex.toUpperCase());
}
return sb.toString().trim();
}
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source==btnSend)
{
String sMsg = taSend.getText().trim();
if (!sMsg.equals(""))
SendData(sMsg);
}
else if (source==btnConnect)
{
Connect();
}
else if (source==btnDisConnect)
{
DisConnect();
}
}
}