Java Swing编写udp数据传输的demo
事情是这个样子的,那天上软件工程课,老师和我们说,让我们一个星期内编写出一个udp进行数据传输的聊天程序,高级软件工程那本教科书上有响应的demo,但是那个代码是用VB写的,考古呢!!我就想着怎么用java来写一个,所以就有了以下内容了。
首先给大家看看作品演示
一、项目需求
1.使用UDP
2.可视化
3.可以传输文本,语音
二、项目准备
0.下载jdk安装配置环境变量,这一步网上到处都是教材,就不拿出来写了!
1.下载eclipse 2020版(idea 在Java swing中不是很好用,所以用eclipse)
2.有了这些还不够,我们还需要swing 插件
3.我们需要一个gson.jar包
三、新建项目
1.点击File-> New->JavaProject2.填写项目名称,点击finish3.这里Module name随便写,因为我们还要删除它
4. 删除这个自动生成的java文件,不然系统运行不起来
5. 右击 src->Other->找到下图的这个文件夹
6.填写包名和类名,com.ahut是安徽工业大学的意思,你们可以换自己名字,点击finish
7.把Main中内容删除,新建一个入口函数
开始写代码
首先开始明确我们的架构
两个客户端之间不直接产生关系,都是通过服务器来传递消息
创建消息的Bean
1.新建一个Class ,起名叫MessageBean
public class MessageBean {
private String name;
private String content;
private int type;//0正常的一个字符串,1则是语音
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
2.编写服务端
创建一个MyService的class ,这个就是我们的客户端
我们需要一个UDP对象-> private static DatagramSocket socket;
DatagramSocket 在java中就是UDP传输的实体类
更好的解释请看视频!!!!
代码在此
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;
import com.google.gson.Gson;
public class MyService extends Thread{
public static int PORT=10005;
private static DatagramSocket socket;
private static ArrayList<ClientActivity> mList=new ArrayList<>();
public MyService() {
try {
socket=new DatagramSocket(PORT);
} catch (SocketException e) {
e.printStackTrace();
}
}
public static void loginGroups(ClientActivity clientActivity) {
if(clientActivity==null)
return;
mList.add(clientActivity);
}
private void receiveMessage() {
byte[] buf=new byte[1024];
DatagramPacket datagramPacket=new DatagramPacket(buf, buf.length);
while(true) {
try {
socket.receive(datagramPacket);
String msg=new String(datagramPacket.getData(),0,datagramPacket.getLength());
Gson gson=new Gson();
MessageBean bean=gson.fromJson(msg, MessageBean.class);
for(ClientActivity clientActivity:mList) {
//发送数据给每一个客户端
clientActivity.pushMessage(bean);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
// while(true) {
receiveMessage();
// }
}
}
3.编写客户端
这个就是我们可以看到的界面,新建ClientActivity继承JFrame
我们需要一个UDP对象-> private static DatagramSocket socket;
DatagramSocket 在java中就是UDP传输的实体类
TargetDataLine在Java中是录音的实体类
代码在此
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.DataLine.Info;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.File;
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.awt.event.ActionEvent;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import com.google.gson.Gson;
import javax.swing.JTextArea;
public class ClientActivity extends JFrame{
private String name;
private JTextField textField;
private DatagramSocket socket;
private InetAddress ip;
private JTextArea textArea;
private JButton playBtn;
private AudioFormat format;
public TargetDataLine targetDataLine;
private boolean isStartAduio=true;
public ClientActivity(String name) {
super("聊天客户端:"+name);
this.name=name;
setSize(500, 500);
getContentPane().setLayout(null);
initLayout();
initUdp();
show();
}
private void initLayout() {
JButton sendBtn = new JButton("发送");
sendBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String msg=textField.getText();
sendMessage(msg, 0);
}
});
sendBtn.setBounds(366, 419, 97, 23);
getContentPane().add(sendBtn);
textField = new JTextField();
textField.setBounds(10, 419, 346, 23);
getContentPane().add(textField);
textField.setColumns(10);
JButton soundRecordBtn = new JButton("点击录音");
soundRecordBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isStartAduio) {
captureAudio();
soundRecordBtn.setText("点击结束");
}else {
targetDataLine.stop();
targetDataLine.close();
soundRecordBtn.setText("点击录音");
sendMessage("给您发送了语言,请点击播放", 1);
playBtn.setVisible(true);
}
isStartAduio=!isStartAduio;
}
});
soundRecordBtn.setBounds(48, 375, 97, 23);
getContentPane().add(soundRecordBtn);
playBtn = new JButton("点击播放");
playBtn.setVisible(false);
playBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
playAduio();
playBtn.setText("正在播放...");
}
});
playBtn.setBounds(292, 375, 97, 23);
getContentPane().add(playBtn);
textArea = new JTextArea();
textArea.setBounds(10, 0, 466, 365);
getContentPane().add(textArea);
}
private void initUdp() {
MyService.loginGroups(this);
try {
socket=new DatagramSocket();
ip=InetAddress.getByName("127.0.0.1");
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public void pushMessage(MessageBean bean) {
textArea.append(bean.getName()+":"+bean.getContent()+"\n");
if(bean.getType()==0) {
playBtn.setVisible(false);
}else {
playBtn.setVisible(true);
}
}
private void sendMessage(String msg,int type) {
MessageBean bean=new MessageBean();
bean.setName(name);
bean.setContent(msg);
bean.setType(type);
Gson gson=new Gson();
String json=gson.toJson(bean);
byte[] bytes=json.getBytes();
DatagramPacket datagramPacket=new DatagramPacket(bytes, bytes.length,ip,MyService.PORT);
try {
socket.send(datagramPacket);
} catch (IOException e) {
e.printStackTrace();
}
}
private void captureAudio() {
format=getAudioForamt();
DataLine.Info dataLineInfo=new DataLine.Info(TargetDataLine.class, format);
try {
targetDataLine=(TargetDataLine) AudioSystem.getLine(dataLineInfo);
new CaptureThread().start();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
private AudioFormat getAudioForamt() {
float sampleRate=11025.0f;
int sampleSizeInBits=16;
int channels=1;
boolean signed=true;
boolean bigEndian=false;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
class CaptureThread extends Thread{
@Override
public void run() {
AudioFileFormat.Type fileType=AudioFileFormat.Type.WAVE;
File audioFile=new File("chat.wav");
try {
targetDataLine.open(format);
targetDataLine.start();
AudioSystem.write(new AudioInputStream(targetDataLine), fileType, audioFile);
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void playAduio() {
AudioInputStream as;
try {
as=AudioSystem.getAudioInputStream(new File("chat.wav"));
AudioFormat format=as.getFormat();
SourceDataLine sdl=null;
DataLine.Info info=new DataLine.Info(SourceDataLine.class,format);
sdl=(SourceDataLine) AudioSystem.getLine(info);
sdl.open(format);
sdl.start();
int nBytesRead=0;
byte[] abData=new byte[512];
while(nBytesRead!=-1) {
nBytesRead=as.read(abData,0,abData.length);
if(nBytesRead>=0) {
sdl.write(abData, 0, nBytesRead);
}
}
sdl.drain();
sdl.close();
playBtn.setVisible(false);
playBtn = new JButton("点击播放");
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
}
3.我们需要一个开启服务和打开界面的入口类Main.java
代码在此
public class Main {
public static void main(String[] args) {
new ClientActivity("小红");
new ClientActivity("小明");
MyService myService=new MyService();
myService.start();
}
}