两台计算机间进行通讯需要以下三个条件: IP地址、协议、端口号
一、IP地址与端口
1.IP地址
作用:每台计算机都必须有一个唯一的标识—IP地址;
格式:32位,4个字节,常用点分十进制的格式表示,例如:192.168.1.100 ;
注意:127.0.0.1 是固定ip地址,代表当前计算机,相当于面向对象里的 “this”;
2.端口
作用:区分一台主机的多个不同应用程序;
格式:端口号范围为0-65535;
注意:0-1023位为系统保留;
3.Socket套接字
网络上具有唯一标识的IP地址和端口组合在一起才能构成唯一能识别的标识符套接字;
二、InetAddress
InetAddress:InetAddress类用于标识网络上的硬件资源,标识互联网协议(IP)地址;
import java.net.InetAddress;
public class demo {
public static void main(String[] args) throws Exception {
//创建对象,用于获取本机IP信息
InetAddress lh = InetAddress.getLocalHost();
//返回本机的主机名
System.out.println(lh.getHostName());
//返回本机的IP地址
System.out.println(lh.getHostAddress());
//创建对象,用于获取其他主机IP信息
//返回主机名的IP地址
InetAddress oth1 = InetAddress.getByName("lzg-PC");
//检查IP地址格式的有效性
InetAddress oth2 = InetAddress.getByName("192.168.0.104");
System.out.println(oth1 + "\n" +oth2);
console结果:
lzg-PC
192.168.0.104
lzg-PC/192.168.0.104
/192.168.0.104
}
}
三、UDP编程
1.UDP协议:(用户数据报协议)是无连接的、不可靠的、无序的,速度快;
2.编程类:
- DatagramPacket类:数据包类
- DatagramSocket类:端到端通信的类
3.示例:
接收端:
1)创建DatagramSocket对象,必须制定端口号;
2)创建DatagramPacket对象,用于接收数据包;
3)接受客户端发送的数据信息;
4)读取数据
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ss {
public static void main(String[] args) throws Exception {
byte[] da = Receiver();
int len = da.length;
System.out.println("发送的:" + new String(da,0,len));
}
public static byte[] Receiver() throws Exception {
//创建接收器对象
DatagramSocket ds = new DatagramSocket(2333);
//定义数据包参数
byte[] buf = new byte[1024];
int length = buf.length;
//创建用于存储接收数据的数据包对象
DatagramPacket dp = new DatagramPacket(buf, length);
//接收数据包
System.out.println("等待数据中...");
ds.receive(dp);
System.out.println("数据接收中...");
//关闭接收器
ds.close();
System.out.println("来自:" + dp.getAddress() + "接收完成关闭");
return dp.getData();
}
}
发送端:
1)创建DatagramSocket对象;
2)创建DatagramPacket对象,将要发送的信息,IP,端口打包成数据包;
3)发送数据;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
public class demo {
public static void main(String[] args) throws SocketException, Exception {
//使用scanner来从控制台中输入数据作为发送数据
Scanner s = new Scanner(System.in);
System.out.println("请输入发送的数据:");
byte[] buf = s.nextLine().getBytes();
s.close();
Sender(buf);
}
public static void Sender(byte[] buf) throws SocketException, Exception{
//创建发送器对象
DatagramSocket ds = new DatagramSocket();
//定义数据包参数
int length = buf.length;
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 2333;
//创建数据包对象
DatagramPacket dp = new DatagramPacket(buf, length, address, port);
//发送数据包
ds.send(dp);
System.out.println("数据发送中...");
//关闭发送器
ds.close();
System.out.println("发送完成关闭");
}
}
四、TCP编程
1.TCP协议:面向连接的、可靠的、有序的、以字节流的方式发送数据,通过三次握手方式建立连接,形成传输数据的通道,在连接中进行大量数据的传输,效率会稍低;
2.编程类:
- Socket类:客户端
- ServerSocket类:服务器端
3.简单示例:
客户端:
1)创建Socket对象,指定IP和端口;
2)通过Socket对象获取输出流,调用流的write()方法写入数据到服务器端;
3)通过Socket对象获取输入流,调用流的read()方法读取服务器端返回的数据;
4)关闭流、Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Cilent {
public static void main(String[] args) throws Exception {
//创建socket对象
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 2345;
Socket cl = new Socket(address , port);
//获取输出流
System.out.println("数据等待中...");
OutputStream os = cl.getOutputStream();
//在控制台里写入数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入要发送的数据:");
byte[] b = sc.nextLine().getBytes();
sc.close();
os.write(b);
System.out.println("数据已发送至:"+cl.getInetAddress());
//获取输入流
System.out.println("等待服务器端响应...");
InputStream is = cl.getInputStream();
//读取数据
byte[] buf = new byte[1024];
is.read(buf);
System.out.println("服务器返回数据:"+new String(buf,0,buf.length));
//关闭
is.close();
os.close();
cl.close();
}
}
服务器端:
1)创建ServerSocket对象,指定端口;
2)调用accept()方法,获取连接到服务器端的客户端(Socket)对象;
3)通过Socket对象获取输入流,调用流的read()方法读取客户端发送的数据;
4)通过Socket对象获取输出流,调用流的write()方法写入数据到客户端;
5)关闭流、Socket、ServerSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
int port = 2345;
ServerSocket se = new ServerSocket(port);
System.out.println("等待数据中...");
//获取客户端对象
Socket obj = se.accept();
System.out.println(obj.getInetAddress()+"客户端发来数据");
//获取输入流
InputStream is = obj.getInputStream();
//读取数据
byte[] b = new byte[1024];
is.read(b);
System.out.println("客户端发来数据:"+new String(b,0,b.length));
//获取输出流
OutputStream os = obj.getOutputStream();
//在控制台里写入数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入要返回的数据:");
byte[] buf = sc.nextLine().getBytes();
sc.close();
os.write(buf);
System.out.println("服务器已响应");
//关闭
os.close();
is.close();
obj.close();
se.close();
}
}
4.文件上传示例:
客户端:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.text.DecimalFormat;
public class cilent {
public static void main(String[] args) throws Exception {
//创建socket对象
InetAddress address = InetAddress.getByName("192.168.0.104");
int port = 2345;
Socket cl = new Socket(address, port);
//获取对象的输出流
OutputStream out = cl.getOutputStream();
//创建文件输入流对象,用来将需要发送的文件写入到输出流
File f = new File("server.txt");
while(f.createNewFile()) {
System.out.println(f.getName() + "文件创建成功!");
}
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] b = new byte[1024];
//计算写入进度
long size = f.length();
DecimalFormat df = new DecimalFormat("#.0");
int len = 0;
while((len = bis.read(b)) != -1) {
//写入
out.write(b, 0 , len);
if(1024>len) {
System.out.println("数据已全部发送");
}
else {
String rate = df.format((1024*100)/size);
System.out.println("数据已发送:"+ rate +"%");
len -=1024;
}
//等待服务器响应
System.out.println("等待服务器响应");
InputStream in = cl.getInputStream();
byte[] buf = new byte[1024];
in.read(buf);
System.out.println("服务器返回:"+new String(buf,0,buf.length));
}
bis.close();
fis.close();
cl.shutdownOutput();
cl.close();
}
}
console结果:
数据已发送:63.0%
等待服务器响应
服务器返回:服务器已收到
数据已全部发送
等待服务器响应
服务器返回:服务器已收到
服务器端:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
//创建serversocket对象
int port = 2345;
ServerSocket ss = new ServerSocket(port);
while(true) {
//获取客户端对象
System.out.println("等待数据中...");
Socket ac = ss.accept();
//获取对象的输入流
InputStream is = ac.getInputStream();
//读取
byte[] b = new byte[1024];
File f = new File("servercopy.txt");
if(f.createNewFile()) {
System.out.println(f.getName()+"文件创建成功");
}
FileOutputStream fis = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(fis);
int len = 0;
while((len = is.read(b)) != -1) {
bos.write(b,0,len);
System.out.println("数据写入成功");
//
OutputStream out = ac.getOutputStream();
out.write("服务器已收到".getBytes());
}
bos.close();
ac.close();
}
}
}
5.多线程使用示例:
在这里插入代码片
五、URL类