一、基于 UDP 协议的 Socket 编程
1.端口选择
已知端口:0~1023,为固定服务保留。
已注册的端口:1024~49151,供普通用户的普通用户进程或程序使用。
动态或私用端口: 49152~65535,没有注册服务。
2.原理
a.基于UDP的套接字就是数据报套接字(ava.net.DatagramSocketj)。
b.两个都要先构造好相应的数据包(java.net.DatagramPacket)。
c.在DatagramPacket包中的函数 intgetLength()返回实际接受的字节数,byte[]getData()返回接受到的数据。
d.要想接受端给发送端回信息,就需要知道发送端的IP地址InetAddress getAddress()和发送端进程所绑定的端口号int getPort()。
e.数据报套接字发送成功之后,就相当于建立了一个虚连接,双方可以发送数据。
3.编写代码(用Java的Swing技术)
(1)首先,建立通信界面的可视化视图,用Java的JFrame窗口建立;用init()函数初始化这个页面;
public static void init() {
JFrame frame = new JFrame("UDPServer"); //初始化一个frame窗口
frame.setBounds(100, 100, 700,500 ); //setBounds(int left, int top, int right, int bottom)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置退出方法
frame.getContentPane().setLayout(null);
JLabel lblip = new JLabel("对方IP:");
lblip.setBounds(47, 39, 72, 18);
frame.getContentPane().add(lblip);
JLabel lblip_1 = new JLabel("用户名:");
lblip_1.setBounds(47, 89, 72, 18);
frame.getContentPane().add(lblip_1);
JLabel lblip_2 = new JLabel("对方端口:");
lblip_2.setBounds(320, 39, 80, 18);
frame.getContentPane().add(lblip_2);
JLabel label = new JLabel("本机端口:");
label.setBounds(320, 89, 80, 18);
frame.getContentPane().add(label);
JTextField textField = new JTextField("127.0.0.1");
textField.setBounds(100, 36, 150, 27);
frame.getContentPane().add(textField);
JTextField textField_1 = new JTextField("徐武莉",10);
textField_1.setEditable(false);
textField_1.setBounds(100, 86, 150, 27);
frame.getContentPane().add(textField_1);
JTextField textField_2 = new JTextField("6000",10);
textField_2.setBounds(390, 36, 100, 27);
frame.getContentPane().add(textField_2);
JTextField textField_3 = new JTextField("9000",10);
textField_3.setBounds(390, 86, 100, 27);
frame.getContentPane().add(textField_3);
textArea= new JTextArea(10,15);
textArea.setBounds(47, 133, 600, 191);
textArea.setLineWrap(true);
JScrollPane jsp = new JScrollPane(textArea);//给文本区添加滚动条
frame.getContentPane().add(textArea);
JTextField text_send = new JTextField();
text_send.setBounds(47, 346, 450, 31);
frame.getContentPane().add(text_send);
text_send.setColumns(10);
JButton button = new JButton("发送");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String message=textField_1.getText()+":"+text_send.getText()+"\n";
int port=Integer.parseInt(textField_2.getText());
textArea.append(message);
System.out.println("发送信息为:"+message+"对方端口号:"+port);
UDPSend usend=new UDPSend(message,port);
usend.send();
}
});
button.setBounds(520, 346, 113, 31);
frame.getContentPane().add(button);
frame.setVisible(true);
}
(2)新建一个UDPSend()的程序进行发送数据;
在这个程序中,用DatagramPacket类表示数据报包。数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。
dp = new DatagramPacket(mesg.getBytes(), mesg.getBytes().length,
InetAddress.getByName("localhost"),port);
对数据报的数据进行赋值,mesg.getBytes()表示消息的字节数,mesg.getBytes().length表示消息字节数的长度,调用InetAddress类的getByName()方法去获得本地服务器的IP号InetAddress.getByName("localhost"),port为要发送的端口号;
DatagramSocket() 类用来构造数据报套接字并将其绑定到本地主机上任何可用的端口。 ds.send(dp)为调用DatagramSocket() 类的send()方法发送数据包;
(3)发送按键的按钮监听,当按“发送”时,获取发送的数据,并且调用UDPSend类进行数据的发送;
3.button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String message=textField_1.getText()+":"+text_send.getText()+"\n";
int port=Integer.parseInt(textField_2.getText());
textArea.append(message);
System.out.println("发送信息为:"+message+"对方端口号:"+port);
UDPSend usend=new UDPSend(message,port);
usend.send();
}
});
用addActionListener(new ActionListener),用内置函数去对监听按钮事件,当点击发送时,用.getText()函数去获取文本框的数据;并且调用函数进行数据传递和send的发送
(4)在Main()函数里面用ds=new DatagramSocket(9000)去绑定端口号,
byte[] buf = new byte[1024],去对数据new一个字节为1024的数组大小;
dp=new DatagramPacket(buf,buf.length)去对数据包进行初始化;
(5)接收数据
while(true){
try {
ds.receive(dp);
String info=new String(buf,0,dp.getLength());
textArea.append(info);
} catch (IOException e) {
e.printStackTrace();
}
用while(true)一直去监听发送过来的数据,用ds.receive(dp)去接收数据包的数据,并且将数据转换为string的类型数据,将内容显示在textArea的输入框中;
4.界面示意
(1)基于UDP的socket点对点通信
a.两个客户端进行点对点通信,都是在本地服务器上进行通信,因此地址都是127.0.0.1;初始化两方的端口分别为6000和9000;
b.向对方发送信息,两方都显示发送的信息结果,说明信息发送成功
c.回复对方信息,由以下信息可以看出,双方可以进行正常的通信,成功实现了点对点通信的功能;