上一篇我们讲了通过TCP方式实现网络通信软件开发的原理,思路及实现,今天跟大家谈谈Socket通信中UDP方式通信的软件开发步骤及主要代码讲解,UDP实现方式实现的通信软件特点是不分客户端与服务器端,一个程序既是客户端与是服务器端,典型软件是一些局域网的聊天软件,如飞鸽等软件。

    UDP方式通信主要用到了java.net包中的3个类分别是DatagramPacket类,DatagramSocket类与InetAddress类,下面通过实现一个简易聊天软件小项目来讲解他们的使用方法,代码如下:

package T16;


import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.FlowLayout;

import java.awt.GridLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.net.SocketException;

import java.net.UnknownHostException;

import java.util.Date;


import javax.swing.BorderFactory;

import javax.swing.JButton;

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JTextField;

/**

 * UDP通信的聊天软件

 * 

 * */

public class UDPChat extends JFrame implements ActionListener{


private JLabel lblPort,lblAddr,lblPort2;

private JTextField txtPort,txtAddr,txtPort2;

private JButton btnConn,btnSend,btnClose;

private JEditorPane txtReceive,txtSend;

public UDPChat(int n){

}

private UDPChat(int n,int m){

}

public UDPChat() {

super("UDP通信的聊天软件");

lblPort = new JLabel("本机端口:",JLabel.RIGHT);

lblPort2 = new JLabel("对方端口:",JLabel.RIGHT);

lblAddr = new JLabel("对方地址:",JLabel.RIGHT);

txtPort = new JTextField("8888",5);

txtPort2 = new JTextField("9999",5);

InetAddress ipaddr =null;

try {

ipaddr = InetAddress.getLocalHost();

} catch (UnknownHostException e) {

e.printStackTrace();

}

txtAddr = new JTextField(ipaddr.getHostAddress(),10);

btnConn = new JButton("连接(C))");

btnConn.setMnemonic('C');

JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

topPanel.add(lblPort);

topPanel.add(txtPort);

topPanel.add(lblAddr);

topPanel.add(txtAddr);

topPanel.add(lblPort2);

topPanel.add(txtPort2);

topPanel.add(btnConn);

txtReceive = new JEditorPane();

txtSend = new JEditorPane();

JPanel centerPanel = new JPanel(new GridLayout(2,1,5,10));

centerPanel.add(txtReceive);

txtReceive.setBorder(BorderFactory.createLoweredBevelBorder());

//接收框不能编辑

txtReceive.setEditable(false);

txtSend.setBorder(BorderFactory.createLoweredBevelBorder());

centerPanel.add(txtSend);

btnSend = new JButton("发送(S)");

btnSend.setMnemonic('S');

btnClose = new JButton("退出(X)");

btnClose.setMnemonic('X');

JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));

bottomPanel.add(btnSend);

bottomPanel.add(btnClose);

add(topPanel,BorderLayout.NORTH);

//centerPanel.setBackground(Color.RED);

add(centerPanel,BorderLayout.CENTER);

add(bottomPanel,BorderLayout.SOUTH);

btnConn.addActionListener(this);

btnSend.addActionListener(this);

btnClose.addActionListener(this);

//发送按钮禁用

btnSend.setEnabled(false);

setSize(600, 400);

setVisible(true);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}


//创建内部类,实现接收线程

class ReceiveThread extends Thread{

DatagramSocket socket;

public ReceiveThread() {

try{

int port = Integer.parseInt(txtPort.getText().trim());

socket = new DatagramSocket(port);

}catch(Exception e){

e.printStackTrace();

}

}

@Override

public void run() {

byte[] b = new byte[1024];

DatagramPacket packet = new DatagramPacket(b,b.length);

while(true){

try {

//接收数据

socket.receive(packet);

//转换为字符串

String str = new String(b,0,packet.getLength());

//显示在接收框

String content = txtReceive.getText();

content += new Date().toLocaleString()+"\n";

content += str+"\n";

txtReceive.setText(content);

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

public static void main(String[] args) {

//UDPChat chat = new UDPChat();

try {

Class.forName("T16.UDPChat").newInstance();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}


@Override

public void actionPerformed(ActionEvent e) {

if(e.getSource()==btnConn){

btnConn.setEnabled(false);

btnSend.setEnabled(true);

//启动线程

new ReceiveThread().start();

}else if(e.getSource()==btnSend){

//发送内容

String str = txtSend.getText().trim();

if(str.equals("")){

JOptionPane.showMessageDialog(this, "请输入要发送的内容");

return;

}

//把要发送的内容显示到接收框

String content = txtReceive.getText();

content += new Date().toLocaleString()+"\n";

content += str+"\n";

txtReceive.setText(content);

try {

//设置对方IP地址

InetAddress ip = InetAddress.getByName(txtAddr.getText().trim());

//设置对方的端口

int port = Integer.parseInt(txtPort2.getText().trim());

//创建发送包

byte b[] = str.getBytes();

DatagramPacket p = new DatagramPacket(b,b.length,ip,port);

//创建DatagramSocket发送

DatagramSocket socket = new DatagramSocket();

//发送

socket.send(p);

//清空发送框的内容

txtSend.setText("");

} catch (UnknownHostException e1) {

e1.printStackTrace();

} catch (SocketException e2) {

e2.printStackTrace();

} catch (IOException e3) {

e3.printStackTrace();

}

}else if(e.getSource()==btnClose){

System.exit(0);

}

}

}


该程序必须同启动2个实例才能实现在局域网聊天,互相设置对方的端口与IP地址即可。

本人从事软件项目开发20年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂,

讲师课堂链接:https://edu.51cto.com/lecturer/8307455.html

关于网络即时通讯,多线程等技术的详细介绍内容很多,如果大家有兴趣可以看看我的 java从入门到精通+QQ即时通讯软件项目实训的教学视频,链接地址:http://edu.51cto.com/course/6946.html