黑马程序员 java基础之网络编程UDP
InetAddress类
//测试InetAddress类
import java.net.InetAddress;
public class InetAddressTest
{
public static void main(String[] args)throws Exception //抛出异常
{
testInet();
}
public static void testInet()throws Exception //抛出异常
{
InetAddress localAdd = InetAddress.getLocalHost(); //实例化InetAddress类
InetAddress remoteAdd = InetAddress.getByName("www.baidu.com");
System.out.println("本机ip:"+localAdd.getHostAddress()); //得到本地Ip地址
System.out.println("百度ip:"+remoteAdd.getHostAddress()); //得到远程IP地址
System.out.println("本机是否可达:"+localAdd.isReachable(5000)); //判断地址是否可达,同时指定超时时间
}
}
TCP和UDP
UDP:
1. 将数据源和目的封装成数据包,不需要建立连接。
2. 每个数据报的大小限制在64k内。
3. 因无连接,是不可靠协议。
4. 不需要建立连接,速度快。
TCP:
1. 建立连接,形成传输数据的通道。
2. 在连接中进行大数据量传输。
3. 通过三次握手完成连接,是可靠协议。
4. 必须建立连接,效率稍低。
注:三次握手:
第一次:我问你在么?
第二次:你回答在。
第三次:我反馈哦我知道你在。
Socket(UDP传输)
1. Socket就是为网络服务提供的一种机制。
2. 通信的两端都有Socket。
3. 网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
UDP传输:
类DatagramSocket
构造:DatagramSocket()
构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port)
创建数据报套接字并将其绑定到本地主机上的指定端口。
方法:void receive(DatagramPacket p)
从此套接字接收数据报包。
void send(DatagramPacket p)
从此套接字发送数据报包。
void close()
关闭此数据报套接字。
类DatagramPacket
构造:
DatagramPacket(byte[] buf, int length)
构造 DatagramPacket,用来接收长度为 length 的数据包。
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
方法:
InetAddress getAddress()
返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
byte[] getData()
返回数据缓冲区。
int getLength()
返回将要发送或接收到的数据的长度。
int getPort()
返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
//udp 发送端
import java.net.*;
public class UdpSend
{
public static void main(String[] args) throws Exception
{
//1. 创建udp socket,建立端点,随机端口
DatagramSocket ds = new DatagramSocket();
//2. 确定数据,并封装成数据包
String str = "HelloWorld!";
byte[] buf = str.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.101"), 3344);
//3. 通过DatagramSocket的send方法,将数据包dp发送出去,
ds.send(dp);
//4. 关闭资源
ds.close();
}
} 1 //udp 接收端
import java.net.*;
public class UdpReceive
{
public static void main(String[] args) throws Exception
{
//1. 创建udp socket,建立断点,并指定端口
DatagramSocket ds = new DatagramSocket(3344);
//2. 定义数据包,用于存储数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3. 通过DatagramSocket中的receive方法将收到的数据存入数据包dp中
ds.receive(dp); //receive为阻塞式方法。
//4. 通过DatagramPacket中的方法获取数据包dp中的数据
String ip = dp.getAddress().getHostAddress();
byte[] buff = dp.getData();
int length = dp.getLength();
String data = new String(buff,0,length);
int port = dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
//5. 关闭资源
ds.close();
}
1 /*
编写一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。
*/
import java.io.*;
import java.net.*;
class Send implements Runnable //继承Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run() //发送端
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line=br.readLine())!=null)
{
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 3344);
ds.send(dp);
if ("886".equals(line))
{
break;
}
}
}
catch (Exception e)
{
throw new RuntimeException("发送端失败!");
}
}
}
class Rec implements Runnable //继承Runnable
{
private DatagramSocket ds;
public Rec(DatagramSocket ds)
{
this.ds = ds;
}
public void run() //接受端
{
try
{
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());
if ("886".equals(data))
{
System.out.println(ip+"离开聊天室!");
break;
}
System.out.println(ip+"::"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败!");
}
}
}
public class ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket recSocket = new DatagramSocket(3344);
new Thread(new Send(sendSocket)).start();
new Thread(new Rec(recSocket)).start();
}