一、InetAddress类
1.1 作用
可以表示互联网协议地址
1.2 常用方法
- public static InetAddress getByName(String host)
获得一个InetAddress对象实例;
host可以是主机名或者主机IP地址 - public String getHostAddress()
获取当前计算机所在网络中的IP地址 - public String getHostName()
获取主机名 - getLocalHost()
获取主机名和IP地址
1.3 案例
public class Thread {
public static void main(String[] args) throws UnknownHostException {
InetAddress address = InetAddress.getByName("DESKTOP-TSM707T");
System.out.println(address.getHostName());
System.out.println(address.getHostAddress());
System.out.println(address.getLocalHost());
}
}
结果:
DESKTOP-TSM707T
192.168.16.104
DESKTOP-TSM707T/192.168.16.104
注意:计算机名称可以:
此电脑—>属性—>高级系统设置—>计算机名
二、UDP协议
2.1 特点
- 客户端与服务端不需要建立链接
- 发送数据速度较TCP快
- 发送数据有大小限制
2.2 UDP发送数据步骤
- 创建客户端Socket对象
- 将数据打包,包里的数据包括要发送的数据,数据的长度,发送端的IP,端口号,注意数据是以字节流的形式打包的。
- 发送数据
2.3 UDP发送数据示例
public class Thread {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
byte[] bytes = "UDP发送端".getBytes();
InetAddress address = InetAddress.getByName("DESKTOP-TSM707T");
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address,8823);
socket.send(packet);
}
}
2.4 UDP接收数据步骤
- 创建带有端口号的服务端Socket对象
- 创建数据包对象
- Socket对象接收发送端发过来的数据包
- 从包中获取数据
- 可以不关闭服务端对象
2.5 UDP接受数据示例
public class receive {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8823);
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
System.out.println("UDP发送端信息已经过来");
socket.receive(packet);
byte[] data = packet.getData();
System.out.println(packet.getAddress().getHostName() + "发送过来的消息是:" + new String(data));
socket.close();
}
}
2.6 UDP输出指定路径文件内容
难点是:
- 怎么将文件中读出的数据打包
用的是BufferedReader类中的readLine()方法获取数据,然后发送 - 怎么将包中的数据读出
可以在死循环里一直新建包队象,一直等待接受包然后读数据
注意:
UDP接受数据时,新建一个包对象只能接受该包对象大小的数据,只能输出一行!!!!
发送端:
public class send_file {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
FileInputStream inputStream = new FileInputStream("D:a.java");
int i;
DatagramPacket packet = null;
byte[] bytes = new byte[1024];
InetAddress byName = InetAddress.getByName("MS-20181121ZVTC");
while ((i = inputStream.read(bytes)) != -1) {
packet = new DatagramPacket(bytes,1024, byName, 1111);
socket.send(packet);
System.out.print(new String(bytes));
}
socket.close();
}
接收端:
public static void main(String[] args) throws IOException {
FileOutputStream outputStream = new FileOutputStream("D:\\b.java");
DatagramSocket socket = new DatagramSocket(1111);
DatagramPacket datagramPacket = null;
byte[] bytes = new byte[1024];
while (true){
datagramPacket = new DatagramPacket(bytes,bytes.length );
socket.receive(datagramPacket);
byte[] data = datagramPacket.getData();
outputStream.write(data);
System.out.println(new String(data));
}
}
2.7 简单UDP聊天
思路:
声明发送端线程和接收端线程,开辟两个聊天室,分别有一个发送端和接收端线程,sleep的作用是确保接收端线程先开启,然后发送端线程再开启。使用InputstreamReader(Syetem.in)从键盘端读取数据。
发送端线程
public class send extends Thread{
int port;
send(int port) {
this.port = port;
}
@Override
public void run() {
try {
//创建发送端Socket对象
DatagramSocket socket = new DatagramSocket();
//从指定路径读取数据
InetAddress address = InetAddress.getByName("DESKTOP-TSM707T");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
byte[] bytes = new byte[1024];
String str = null;
DatagramPacket packet;
while(!(str = in.readLine()).equals("88")) {
packet = new DatagramPacket(str.getBytes(), str.getBytes().length, address, port);
socket.send(packet);
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
接收端线程
public class receive extends Thread{
int port;
public receive(int port) {
this.port = port;
}
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(port);
System.out.println("准备接收数据");
while (true) {
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
socket.receive(packet);
System.out.println("发送端发来信息:" + new String(packet.getData()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
聊天窗口1:
public class talkroom {
public static void main(String[] args) throws InterruptedException {
receive rec = new receive(4212);
send se = new send(2424);
rec.start();
Thread.sleep(10000);
se.start();
}
}
聊天窗口2:
public class talkroom2 {
public static void main(String[] args) throws InterruptedException {
receive rec = new receive(2424);
send se = new send(4212);
rec.start();
Thread.sleep(10000);
se.start();
}
}
三、TCP协议
3.1 特点
- 客户端与服务端需要建立链接
- 不用将数据打包,将数据发送到通道和通过通道获取数据
- 传输数据速度较UDP慢
3.2 TCP发送数据步骤
- 创建带有主机IP和端口号的Socket对象
- 获得输出流
- 往缓冲区写入数据
3.3 TCP发送数据示例
说明:Socket构造函数第一个参数可以是InetAddress对象,也可以是字符串
public class TCP_text {
public static void main(String[] args) throws IOException {
InetAddress address = InetAddress.getByName("DESKTOP-TSM707T");
Socket socket = new Socket(address, 8984);
OutputStream out = socket.getOutputStream();
String str = "TCP发送";
out.write(str.getBytes());
socket.close();
}
}
3.4 TCP接收数据步骤
- 创建带端口号的ServerSocket对象
- 创建Socket对象
- 从通道中获取数据
- 对数据进行操作
3.5 TCP接收数据示例
public class TCP_receive {
public static void main(String[] args) throws IOException {
ServerSocket ser = new ServerSocket(8984);
System.out.println("准备接收数据");
Socket socket = ser.accept();
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = 0;
while((len = in.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
}
}
3.5 用TCP发送文件到接收端
思路:利用BuffferedeReader和BufferWriter来封装通过socket对象获得的输入输出流,然后进行操作。
发送端:
public static void main(String[] args) throws IOException {
InetAddress address = InetAddress.getByName("MS-20181121ZVTC");
Socket socket = new Socket(address, 1111);
File file = new File("D:\\a.java");
BufferedReader re = new BufferedReader(new FileReader(file));
OutputStream out = socket.getOutputStream();
BufferedWriter wri = new BufferedWriter(new OutputStreamWriter(out));
String str = null;
while((str = re.readLine()) != null) {
wri.write(str);
System.out.println(str);
wri.newLine();
wri.flush();
}
re.close();
wri.close();
socket.close();
}
接收端:
public static void main(String[] args) throws IOException {
ServerSocket ser = new ServerSocket(1111);
System.out.println("准备接收数据");
Socket socket = ser.accept();
InputStream in = socket.getInputStream();
BufferedReader re = new BufferedReader(new InputStreamReader(in));
BufferedWriter wri = new BufferedWriter(new FileWriter("D:\\b.java"));
String str = null;
while((str = re.readLine()) != null) {
System.out.println(str);
wri.write(str);
wri.newLine();
wri.flush();
}
re.close();
wri.close();
}
注意:
- void shutdownInput()
禁用此套接字的输出流。
在客户端使用该方法的作用是告诉服务端不再传输数据
3.6 TCP简单聊天
思路:和上面UDP简单聊天一样
注意:一定要注意参数的名称是否写对,否则会造成传参错误而出不来结果;
客户端线程:
public class Send_Thread extends Thread{
int port;
public Send_Thread(int port) {
this.port = port;
}
@Override
public void run() {
try {
InetAddress address = InetAddress.getByName("DESKTOP-TSM707T");
Socket socket = new Socket(address, port);
OutputStream out = socket.getOutputStream();
BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(out));
BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
String str = null;
while(true) {
str = re.readLine();
buf.write(str);
buf.newLine();
buf.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端线程:
public class Receive_Thread extends Thread {
int port;
public Receive_Thread(int port) {
this.port = port;
}
@Override
public void run() {
try {
ServerSocket ser = new ServerSocket(port);
System.out.println("准备接收数据:");
Socket socket = ser.accept();
InputStream in = socket.getInputStream();
BufferedReader re = new BufferedReader(new InputStreamReader(in));
while(true) {
System.out.println(socket.getInetAddress().getHostAddress() + "发来的数据" + re.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
用户1:
public class room1 {
public static void main(String[] args) throws InterruptedException {
Receive_Thread rec = new Receive_Thread(1114);
Send_Thread se = new Send_Thread(2224);
rec.start();
Thread.sleep(10000);
se.start();
}
}
用户2:
public class room2 {
public static void main(String[] args) throws InterruptedException {
Receive_Thread rec = new Receive_Thread(2224);
Send_Thread se = new Send_Thread(1114);
rec.start();
Thread.sleep(10000);
se.start();
}
}