网络编程的三要素
ip地址:ip地址网络中计算设备的唯一标识
ipv4: 占4个字节
ipv6: 占16个字节
ipconfig: 查看本机的ip地址
ping: 检测指定的ip是否能够连接通
注意:ip地址和域名是对应的,需要在工信部门进行备案
端口号:计算设备中连接网络的应用程序的标识(用一个整数表示 0~65535 )
0~1023不建议使用,可能会被系统或者一些知名的软件占用。
80:连接互联网的默认端口号
协议:网络中数据传输的规则
UDP协议:面向无连接,不可靠的通信协议
TCP协议:面向有链接,可靠的通信协议
InetAddress类
InetAddress表示IP地址对象
//获取ip地址对象
InetAddress address = InetAddress.getByName("192.168.72.202");
//获取主机名
System.out.println(address.getHostName());
UDP通信
发送端
//1.创建DatagramSocket对象(邮局)
DatagramSocket ds=new DatagramSocket();
//2.创建DatagramPacket对象(打包裹)
//字节数组:数组中就是需要传输的数据
//数组的长度:数据有多大
//ip地址:数据包需要发送到哪台主机
//端口号:找到对方哪个应用程序接受
byte[] bs="你好世界".getBytes();
int length=bs.length;
InetAddress ip= InetAddress.getByName("127.0.0.1"); //主机本机的ip地址
int port=10000;
DatagramPacket dp=new DatagramPacket(bs,length,ip,port);
//3.发送数据包(把包裹交给邮局)
ds.send(dp);
//4.释放资源
ds.close();
接收端
//1.创建DatagramSocket对象(邮局)
DatagramSocket ds=new DatagramSocket(10000);
//2.创建DatagramPacket对象(用来接受数据的包裹)
byte[] bs=new byte[1024];
DatagramPacket dp=new DatagramPacket(bs,bs.length);
//3.接受数据(自动把接受的到数据,填充到包裹中)
ds.receive(dp); //阻塞(等待发送端发送数据)
//4.解析数据(拆包裹)
byte[] data = dp.getData();
int length = dp.getLength();
//通过数组和长度转换为一个字符串
String str=new String(data,0,length);
//获取ip地址
InetAddress address = dp.getAddress();
System.out.println(address+str);
//5.释放资源
ds.close();
单播、组播、广播
单播:一个发送端 发给 一个接收端
使用DatagramSocket进行发送和接收
组播:一个发送端 发给 多个接收端(一组)
//创建MulticastSocket对象
MulticastSocket MS=new MulticastSocket(10000);
//把当前地址加入组: 组播地址:224.0.1.0
MS.joinGroup(InetAddress.getByName("224.0.1.0"));
广播:一个发送端 发给 所有接收端
//广播地址:255.255.255.255
使用DatagramSocket进行发送和接收
TCP通信
TCP通信的流程图
- 客户端代码
public class Client {
public static void main(String[] args) throws IOException {
//创建Socket对象(客户端),指定服务端的ip和端口号
Socket socket=new Socket("127.0.0.1",10086);
//获取通往服务端的OutputStream
OutputStream out = socket.getOutputStream();
//往服务端写数据
out.write("HelloWorld".getBytes());
/**********************/
//获取输入流,用来读取服务端发过来的数据
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
int len=in.read(bs);
String str=new String(bs,0,len);
System.out.println(str);
//释放资源
socket.close();
}
}
- 服务端代码
public class Server {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
ServerSocket serverSocket=new ServerSocket(10086);
//监听客户端(迎宾)
Socket socket = serverSocket.accept(); //阻塞(等着客户端连接)
//获取输入流对象
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
int len = in.read(bs);
System.out.println(new String(bs,0,len));
/*******************/
//获取通往客户端的输出流
OutputStream out = socket.getOutputStream();
out.write("你好世界".getBytes());
//释放资源
socket.close();
serverSocket.close();
}
}
文件上传的原理
客户端
public class UploadClient{
public static void main(String[] args) throws IOException {
//创建Socket对象
Socket socket=new Socket("127.0.0.1",10010);
//获取输出流(通往服务器)
OutputStream out=socket.getOutputStream();
//读取本地的图片 a.jpg
FileInputStream fis=new FileInputStream("myModule15\\a.jpg");
byte[] bs=new byte[1024];
int len; //记录每次读取的字节个数
while((len=fis.read(bs))!=-1){
//往服务写数据
out.write(bs,0,len);
}
//告诉服务端,数据写完了(告诉服务端可以读取到一个结束标记)
socket.shutdownOutput();
//读取服务端返回的数据
InputStream in = socket.getInputStream();
len= in.read(bs);
System.out.println(new String(bs,0,len));
//释放资源
fis.close();
socket.close();
}
}
服务端
public class UploadServer {
public static void main(String[] args) throws IOException {
//创建服务端的Socket对象
ServerSocket serverSocket=new ServerSocket(10010);
//获取客户端的Socket对象
Socket socket = serverSocket.accept();
//创建FileOutputStream,用来往服务端本地写数据
FileOutputStream fos=new FileOutputStream(new File("C:\\Users\\it\\Desktop\\upload",UUID.randomUUID().toString()+".jpg"));
//获取输入流,读取客户端发过来的数据
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
int len; //每次读取的有效个数
while ((len=in.read(bs))!=-1){
fos.write(bs,0,len);
}
fos.close();
//告诉客户端,上传成功
OutputStream out = socket.getOutputStream();
out.write("上传成功".getBytes());
//释放资源
socket.close();
serverSocket.close();
}
}
多线程改进服务端
- 服务端处理文件上传的任务
//上传文件的任务
public class UploadRunnable implements Runnable {
//上传文件的操作需要一个Socket,但是不知道这个Socket是水
private Socket socket;
public UploadRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
FileOutputStream fos=null;
try {
//创建FileOutputStream,用来往服务端本地写数据
File file=new File("C:\\Users\\it\\Desktop\\upload", UUID.randomUUID().toString()+".jpg");
fos=new FileOutputStream(file);
//获取输入流,读取客户端发过来的数据
InputStream in = socket.getInputStream();
byte[] bs=new byte[1024];
int len; //每次读取的有效个数
while ((len=in.read(bs))!=-1){
fos.write(bs,0,len);
}
//告诉客户端,上传成功
OutputStream out = socket.getOutputStream();
out.write("上传成功".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally { //不管异常发不发生,finally的代码都会执行
//释放本地的流
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
//释放资源
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 服务端代码,来一个Socket就为其开一条线程
public class UploadServer {
public static void main(String[] args) throws IOException {
//创建服务端的Socket对象
ServerSocket serverSocket=new ServerSocket(10010);
while (true){
//获取Socket对象
Socket socket = serverSocket.accept();
//创建线程任务
UploadRunnable r=new UploadRunnable(socket);
//创建线程
new Thread(r).start();
}
//serverSocket.close();
}
}