在学习JAVA的网络编程时学到了UDP,这个东西可以实现不同电脑之间进行数据传输,我就想做一个最简单的聊天窗口,弄了一整天在和老师讨论了一下之后终于做出了一个勉强可以用来聊天的。写了一个比较形象的比喻,应该都能看懂
UDP思路:
- 可以把UDP的思路想象成发快递和收快递的过程,我准备了一份数据想要发给小明,就要先把它打包成一个包裹,然后填上小明的收货地址和门牌号,这样之后包裹就可以通过网络寄给小明,同理,小明想要给我发数据也需要经过同样的流程,而此时的收货地址跟门牌号就应该填我的信息
- DatagramPacket类创建的对象就是用来打包包裹的,构造函数 DatagramPacket(byte data[], int length, InetAddtress address, int port) 其中的参数data[]就是你要发送的内容,length是内容的长度,address是对方的收获地址(IP地址),port是对方的门牌号(端口)
- DatagramSocket类创建的对象就是快递公司,负责发货和送货,发货就是把打包好的数据发送出去,使用send()函数即可,参数为DatagramPacket类的对象;送货需要将包裹准确交到正确的人手中,为了能够收货成功,需要验证一下门牌是否一致,则此时的构造函数应为DatagramSocket(int port)参数为收货人的门牌号(端口),若门牌一致则收获成功
细节:
- 发送数据时IP地址和端口一定要填接收方的,接收数据时端口一定要填自己的
- 接收数据时要用一个新线程
- IP地址可通过查看网络的属性查看 ipv4的那一个地址
通信失败可能出现的问题:
- IP地址和端口没有填写对或者填成了自己主机的
- 发送时的端口和接收时的端口不一致
- 电脑打开了防火墙发送过来的数据被阻隔了
- 两台电脑的无法连接起立,ping 通不过,若是此情况需要进行打洞
- 网络本身的问题,类似校园网之类的网络可能限制比较多容易连接不上
完整代码如下:
主机1
package 网络;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class UDP主机1 {
public static void main(String[] args) {
new A() ;
}
}
class A extends JFrame implements Runnable, ActionListener {
JTextField outMessage = new JTextField(30) ; //输入发送内容的文本框
JTextArea inMessage = new JTextArea(12, 20) ; //输出收到内容的文本区
JButton button = new JButton("发送") ;
JPanel panel = new JPanel() ;
A() {
setBounds(50, 50, 600, 900) ;
setVisible(true) ;
setTitle("一号机");
button.addActionListener(this) ; //点击“发送”按钮进行发送
panel.add(outMessage) ;
panel.add(button) ;
add(new JScrollPane(inMessage), BorderLayout.CENTER) ;
add(panel, BorderLayout.NORTH) ;
Thread thread = new Thread(this) ;
validate() ;
thread.start() ;
}
public void actionPerformed(ActionEvent e) { //发送数据
byte b[] = outMessage.getText().trim().getBytes() ; //将输入到文本框中的内容变为byte类型
try {
InetAddress address = InetAddress.getByName("192.168.43.143") ; //接收方的IP地址
DatagramPacket data = new DatagramPacket(b, b.length, address, 10086) ; //接收方的端口
DatagramSocket mail = new DatagramSocket() ; //快递公司
mail.send(data) ; //发货
}
catch(Exception ee) {}
}
public void run() { //收货
DatagramPacket pack = null ;
DatagramSocket mail = null ;
byte b[] = new byte [8192] ;
try {
pack = new DatagramPacket(b, b.length) ;
mail = new DatagramSocket(10011) ; //收货要验证门牌是否相同
}
catch(Exception e) {}
while(true) {
try {
mail.receive(pack) ; //收获
String message = new String(pack.getData(), 0 ,pack.getLength()) ; //将收到的数据从byte型变为string型
inMessage.append("收到数据来自:"+pack.getAddress()+"\n") ; //将数据输出到文本区
inMessage.append(message+"\n") ;
inMessage.setCaretPosition(inMessage.getText().length()) ; //将光标移动到最后便于下次接收数据从最后开始
}
catch(Exception e) {}
}
}
}
主机2(代码与主机1几乎一致,只需注意IP地址和端口处的不同即可)
package 网络;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class UDP主机2 {
public static void main(String[] args) {
new B() ;
}
}
class B extends JFrame implements Runnable, ActionListener {
JTextField outMessage = new JTextField(12) ;
JTextArea inMessage = new JTextArea(12, 20) ;
JButton button = new JButton("发送") ;
JPanel panel = new JPanel() ;
B() {
setBounds(50, 50, 600, 900) ;
setVisible(true) ;
setTitle("二号机");
button.addActionListener(this) ;
panel.add(outMessage) ;
panel.add(button) ;
Container con = getContentPane() ;
con.add(new JScrollPane(inMessage), BorderLayout.CENTER) ;
con.add(panel, BorderLayout.NORTH) ;
Thread thread = new Thread(this) ;
validate() ;
thread.start() ;
}
public void actionPerformed(ActionEvent e) {
byte b[] = outMessage.getText().trim().getBytes() ;
try {
InetAddress address = InetAddress.getByName("192.168.43.146") ; //IP地址是接收方的
DatagramPacket data = new DatagramPacket(b, b.length, address, 10011) ; //接收方的端口
DatagramSocket mail = new DatagramSocket() ;
mail.send(data) ;
}
catch(Exception ee) {}
}
public void run() {
DatagramPacket pack = null ;
DatagramSocket mail = null ;
byte b[] = new byte [8192] ;
try {
pack = new DatagramPacket(b, b.length) ;
mail = new DatagramSocket(10086) ; //自己的端口
}
catch(Exception e) {}
while(true) {
try {
mail.receive(pack) ;
String message = new String(pack.getData(), 0 ,pack.getLength()) ;
inMessage.append("收到数据来自:"+pack.getAddress()+"\n") ;
inMessage.append(message+"\n") ;
inMessage.setCaretPosition(inMessage.getText().length()) ;
}
catch(Exception e) {}
}
}
}
总结:
- 第一次和老师讨论问题,在交流后找到了一直连不通的原因,以后还是要多找老师讨论
- 这个聊天窗口还是有点问题,每运行一次该程序,关闭程序后这个端口就不能用了,应该是上一次使用后程序没有完全关闭就一直占着那个端口,第二次运行程序就用不了,只能完全关闭编译器然后重新打开或者改一个新的端口,我想的是解决方法是应该在关程序之前要先把这个端口close掉,尝试了一下但暂时做不到close,思路应该是对的但是还没学到具体的方法,等学会了再来完善
- 学校校园网有毒,两个电脑一直连不通,最后是用手机给电脑开热点才连通了
- 最后问一句 有人愿意用我写的东西和我聊天吗 有的话我就做个好的窗口出来