07、UDP-发送端
那么接下来大家,Socket这个通信端点有了,但是传输协议不一样。
所以大家,每个传输协议都有自己的不同端点建立方式。民用传输啊,军用传输啊,是不是不一样啊。
就有了UDP传输的特有的传输方式对应的对象。
那么UDP的Socket服务改怎么建立呢?
我们首先要看到Java.net包有这么个对象、DatagramSocket此类表示用来发送和接受数据报包的套接字。
套接字是不是我们所说的插座啊?明白了吧,这哥们既能发送又能接收。
那么你要搞两个端点的话,是不是着两个端点都要有这个东西啊。OK,这是第一步。
UDP用的对象是DatagramSocket,建立完以后呢我们是不是要把数据发出去啊,
那么这个服务里面是不是要有发送和接受这两个动作啊,发送(void send(DatagramPacket p)),接收(void receive(DatagramPacket p))。
我们前面是不是讲过UDP要把数据封装成包发出去。所以大家他要给我们提供的是不是数据包的对象,数据包里面都封装什么东西。
我们回到之前的到邮寄寄包裹,我们寄包裹是不是,要在包裹里封装饼干(实体数据),
封装包以后是不是要有对方包地址和端口,是不是还要有你自己封装包的地址和端口。
所以源端口源地址,目的端口目的地址。所以把这些都封装成了包对象。
DatagramPacket此类表示数据报包。
数据报包用来实现无线接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。
这个包嘛,既能用来接收数据又能用来封装发送数据。
参数带有地址的,都是用来构造发送数据包的。说到这就不说了,
咱们写个小程序玩一下。注意看,我基本思路说完后,我按照我们创建思想写一下。
注意了玩Socket主要记住的就是这流程。代码查文档就可以。
import java.net.*;
/*
需求:通过udp传输方式,将一段文字数据发送出去。。
思路:
1,建立udp端点 Socket服务。
2,提供并封装数据。
3,通过Socket服务的发送功能将数据包发出去。
4,关闭套接字资源。
*/
class UdpSend{
public static void main(String[] args)throws Exception{
//1,创建udp服务,通过DatagramSocket对象
DatagramSocket ds=new DatagramSocket();
//2,确定数据,封装DatagramPacket(byte[] buf, int length, InetAddress address, int port)
byte[] data="udp ge men lai le".getBytes();
DatagramPacket dp=new DatagramPacket(data,data.length,InetAddress.getByName("10.3.201.87"),10000);
//3,发送
ds.send(dp);
//4,关闭网卡套接字
ds.close();
}
}
08、Udp-接收端
上面是不是没有反应,为什么?接收端没开!
按理说要把两个函数放在两个文件中,但是为了上下看到效果。所以就写到了一个java文件当中。
发送端和接收端是两个独立运行程序。
现在我们是不是有两个应用程序,一个发送应用程序,一个接受应用程序。
/*
需求:定义一个应用程序,用于接受并处理数据。
思路:
1,建立接收端,通常会监听一个端口。
2,定义一个数据包,为了存储接受到的字节数据。
3,通过Socket服务的存储功能将数据包存储进来。
4,通过数据包对象的特有功能将这些不同的数据取出,打印在控制台。
5,关闭。
*/
class UdpReceive{
public static void main(String[] args)throws Exception{
//1,建立udp端点。
DatagramSocket ds=new DatagramSocket(10000);
//2,定义数据包。DatagramPacket(byte[] buf, int length)
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//3,通过Socket服务的存储功能将数据包存储进来。
ds.receive(dp);
//4,通过数据包的方法获取其中数据。
String ip=dp.getAddress().getHostAddress();
String data=new String(dp.getData(),0,dp.getLength());
int port=dp.getPort();
sop(ip+"::"+data+"::"+port);
//关闭
ds.close();
}
public static void sop(Object obj){
System.out.println(obj);
}
}
09、UDP-键盘录入方式数据
为了接受其他人对你接受的数据,你的接收端要一直开着,
import java.net.*;
/*
需求:通过udp传输方式,将一段文字数据发送出去。。
思路:
1,建立udp端点 Socket服务。
2,提供并封装数据。
3,通过Socket服务的发送功能将数据包发出去。
4,关闭套接字资源。
*/
class UdpSend{
public static void main(String[] args)throws Exception{
//1,创建udp服务,通过DatagramSocket对象
DatagramSocket ds=new DatagramSocket(8888);
//2,确定数据,封装DatagramPacket(byte[] buf, int length, InetAddress address, int port)
byte[] data="udp ge men lai le".getBytes();
DatagramPacket dp=new DatagramPacket(data,data.length,InetAddress.getByName("10.3.201.88"),10000);
//3,发送
ds.send(dp);
//4,关闭网卡套接字
ds.close();
}
}
/*
需求:定义一个应用程序,用于接受并处理数据。
思路:
1,建立接收端,通常会监听一个端口。
2,定义一个数据包,为了存储接受到的字节数据。
3,通过Socket服务的存储功能将数据包存储进来。
4,通过数据包对象的特有功能将这些不同的数据取出,打印在控制台。
5,关闭。
*/
class UdpReceive{
public static void main(String[] args)throws Exception{
//1,建立udp端点。
DatagramSocket ds=new DatagramSocket(10000);
while(true){
//2,定义数据包。DatagramPacket(byte[] buf, int length)
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//3,通过Socket服务的存储功能将数据包存储进来。
ds.receive(dp);
//4,通过数据包的方法获取其中数据。
String ip=dp.getAddress().getHostAddress();
String data=new String(dp.getData(),0,dp.getLength());
int port=dp.getPort();
sop(ip+"::"+data+"::"+port);
}
//关闭
//ds.close();
}
public static void sop(Object obj){
System.out.println(obj);
}
}
那么大家我们能不能群聊啊?在我们地址有个比较特殊,广播地址。
大家都知道我们在取地址时候啊,***.***.1.0与192.168.1.255用不了。
192.168.1.0代表网络段,而192.168.1.255代表段里的广播地址。
如果我没找到主机怎么办,我发广播,给这个网段里所有的机器发广播,
import java.net.*;
import java.io.*;
class UdpSend2{
public static void main(String[] args)throws Exception{
DatagramSocket ds=new DatagramSocket();
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bufr.readLine())!=null){
if("886".equals(line))
break;
byte[] buf=line.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("10.2.172.255"),10001);
ds.send(dp);
}
}
}
class UdpReceive{
public static void main(String[] args)throws Exception{
DatagramSocket ds=new DatagramSocket(10001);
while(true){
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip=dp.getAddress().getHostAddress();
String data=new String(dp.getData(),0,dp.getLength());
System.out.println(ip+"::"+data);
}
}
}
10、UDP-聊天
那么大家注意看,我这里有一个发送端、一个接收端。
这是不是一个DOS版的QQ啊?大家是不是一个窗口完成的啊?
可以,发数据的时候,是不是可以收数据,是不是可以同时进行。
那就是多线程,开一个进程跑多个线程。
代码如下:
/*
编写一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
*/
import java.io.*;
import java.net.*;
class Send implements Runnable{
private DatagramSocket ds;
public Send(DatagramSocket ds){
this.ds=ds;
}
public void run(){
try{
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bufr.readLine())!=null){
if("886".equals(line))
break;
byte[] buf=line.getBytes();
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("10.2.172.255"),10002);
ds.send(dp);
}
}
catch(Exception e){
throw new RuntimeException("发送端失败");
}
}
}
class Receive implements Runnable{
private DatagramSocket ds;
public Receive(DatagramSocket ds){
this.ds=ds;
}
public void run(){
try{
while(true){
//2,定义数据包
byte[] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
//3,通过Socket服务将数据保存储。
ds.receive(dp);
//4,通过数据包的方法获取其数据。
String ip=dp.getAddress().getHostAddress();
String data=new String(dp.getData(),0,dp.getLength());
int port=dp.getPort();
sop(ip+"::"+data+"::"+port);
}
}catch(Exception e){
throw new RuntimeException("接收端失败");
}
}
private void sop(Object obj){
System.out.println(obj);
}
}
class ChatDemo{
public static void main(String[] args)throws Exception{
DatagramSocket sendSocket=new DatagramSocket();
DatagramSocket receSocket=new DatagramSocket(10002);
new Thread(new Send(sendSocket)).start();
new Thread(new Receive(receSocket)).start();
}
}