1. IP地址
- 唯一标识网络中的每台主机
- 查看IP地址,ipconfig
- ip地址表示形式: 点分十进制 xx.xx.xx IPV4:4个字节32位,一个字节范围0~255, IPV6,16个字节,ipv6解决网络地址资源数量的问题,也解决了多种接入设备连入互联网的障碍,IPV6还没完全替代IPV4
- ip地址组成=网络地址+主机地址,192.168.16.69 192.168.16为网络地址
ipv4分类
2. 域名和端口
域名:
- 为方便记忆,解决记IP的困难
- 概念:将ip地址映射成域名, HTTP协议映射
端口号:
- 概念:用于标识计算机上某个特定的网络程序
- 表示形式:以整数形式,范围 0~065535
- 0~1024已经被占用,比如ssh 22, ftp 21, smtp 25, http 80
- 常见的网络程序端口号: tomcat:8080 mysql:3306 oracle:1521 sqlserver:1433
3. 网络协议
TCP/IP (Transmission Control Protocol / Internet Protocol)的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议
TCP协议
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手"方式,是 == 可靠 == 的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量传输
- 传输完毕,需释放已建立的连接,效率低
UDP协议
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内,不适合传输大量数据
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源(因为不是面向连接的),速度快
- 举例:厕所通知:发短信
4. InetAddress
-
获取本机InetAddress对象InetAddress getLocalHost()
-
根据指定主机名/域名获取ip地址对象String getByName()
-
获取InetAddress对象的主机名String getHostName()
-
获取InetAddress对象的地址InetAddress getHostAddress()
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddress_ {
public static void main(String[] args) throws UnknownHostException {
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
InetAddress host2 = InetAddress.getByName("WIN-9CPMVKSG0CV");
System.out.println(host2);
InetAddress host3= InetAddress.getByName("www.baidu.com");
System.out.println(host3);
String hostname = host3.getHostName();
System.out.println(hostname);
String hostAddress = host3.getHostAddress();
System.out.println(hostAddress);
}
}
/*
WIN-9CPMVKSG0CV/192.168.10.9
WIN-9CPMVKSG0CV/192.168.10.9
www.baidu.com/39.156.66.18
www.baidu.com
39.156.66.18
5. Socket
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
- 通信的两端都要有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket间的通信。
- Socket:允许程序把网络连接当成一个流,数据在两个Socketl间通过O传输。
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
TCP字节流编程
需求:
- 编写一个服务端,和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务端,发送"hello,server",并接收服务端回发的"helo,client",再退出
- 服务端接收到客户端发送的信息,输出,并发送"hello,client",再退出
输出一定要设置结束标志socket.shutdownOutput();
服务端
package wjx.com.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//客户端,发送 ”hello,world“ 给服务端
public class SocketClient {
public static void main(String[] args) throws IOException {
// 连接服务端(ip,端口)
// 连接InetAddress.getLocalHost()的9999端口,连接成功返回socket对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端连接成功 socket"+socket.getClass());
//
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello, world".getBytes());
socket.shutdownOutput();
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readlen = 0;
while ((readlen = inputStream.read(buf))!=-1){
System.out.println(new String(buf, 0, readlen));
}
outputStream.close();
inputStream.close();
socket.close();
System.out.println("客户端退出");
}
}
/*
客户端连接成功 socketclass java.net.Socket
hello,client
客户端退出
客户端
package wjx.com.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
//主机,服务端
public class SocketServer {
public static void main(String[] args) throws IOException {
// 在本机9999端口监听,等待连接
// 本机没有其他服务监听9999
// ServerSocket可以通过accept返回多个socket[],高并发
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("监听9999端口,等待连接");
// 没有客户端连接时,程序阻塞,等待连接
// 如果有客户端连接,则返回Socket对象,程序继续
Socket socket = serverSocket.accept();
System.out.println("服务端连接成功 socekt" + socket.getClass());
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readlen = 0;
while ((readlen = inputStream.read(buf))!=-1){
System.out.println(new String(buf, 0, readlen));
}
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,client".getBytes());
socket.shutdownOutput();
inputStream.close();
outputStream.close();
socket.close();
serverSocket.close();
}
}
/*
监听9999端口,等待连接
服务端连接成功 socektclass java.net.Socket
hello, world
TCP字符流编程
将socket得到的字节输入输出流包装成字符输入输出流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
之后需要通过flush进行写入
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
package wjx.com.socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServerchar {
public static void main(String[] args) throws IOException {
// 在本机9999端口监听,等待连接
// 本机没有其他服务监听9999
// ServerSocket可以通过accept返回多个socket[],高并发
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("监听9999端口,等待连接");
// 没有客户端连接时,程序阻塞,等待连接
// 如果有客户端连接,则返回Socket对象,程序继续
Socket socket = serverSocket.accept();
System.out.println("服务端连接成功 socekt" + socket.getClass());
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str = bufferedReader.readLine();
System.out.println(str);
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello,client");
bufferedWriter.flush();
socket.shutdownOutput();
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
}
}
TCP传文件
- 编写一个服务端,和一个客户
- .服务器端在8888端口监听
- 客户端连接到服务端,发送一张图片e:\\photo.webp
- 服务器端接收到客户端发送的图片,保存到src下,发送"收到图片"再退出
- 客户端接收到服务端发送的“收到图片”,再退出
工具类
package wjx.com.socket;
import java.io.*;
public class Utils_IO {
public static byte[] streamToByte(InputStream is) throws IOException {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int readlen = 0;
while((readlen=is.read(b))!=-1){
bao.write(b, 0, readlen);
}
byte[] buf = bao.toByteArray();
bao.close();
return buf;
}
public static String streamToString(InputStream is) throws IOException {
BufferedReader bfr = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder() ;
String len = "";
while((len = bfr.readLine())!=null){
sb.append(len);
}
return sb.toString();
}
}
服务端
package wjx.com.socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class FileServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端等待连接");
Socket socket = serverSocket.accept();
BufferedInputStream bfi = new BufferedInputStream(socket.getInputStream());
byte[] buf = Utils_IO.streamToByte(bfi);
String filepath = "E:\\photocopy.webp";
BufferedOutputStream bfo = new BufferedOutputStream(new FileOutputStream(filepath));
bfo.write(buf);
BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bfw.write("收到图片");
bfw.flush();
socket.shutdownOutput();
bfw.close();
bfo.close();
bfi.close();
socket.close();
serverSocket.close();
System.out.println("服务端关闭");
}
}
/*
服务端等待连接
服务端关闭
客户端
package wjx.com.socket;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class FileClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),8888);
System.out.println("客户端连接成功");
String filepath = "E:\\photo.webp";
BufferedInputStream bfi = new BufferedInputStream(new FileInputStream(filepath));
// 将文件转换成字符数组
byte[] buf = Utils_IO.streamToByte(bfi);
// 获取socket输出流,将文件上传,写入数据通道
BufferedOutputStream bfo = new BufferedOutputStream(socket.getOutputStream());
bfo.write(buf);
socket.shutdownOutput();
String s = Utils_IO.streamToString(socket.getInputStream());
System.out.println(s);
bfo.close();
bfi.close();
socket.close();
System.out.println("客户端关闭");
}
}
/*
客户端连接成功
收到图片
客户端关闭
netstat
netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
TCP连接秘密
当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的,是随机的
6.UDP
UDP介绍
- 没有明确的服务端和客户端,演变成数据的发送端和接收端
- 接收数据和发送数据是通过DatagramSocket对像完成,
- 将数据封装到DatagramPacket对像/装包
- 当接收到DatagramPacket对象,需要进行拆包,取出数据
- DatagramSocket可以指定在哪个端口接收数据
UDP流程
- 核心两个类/对象 DatagramSocket与DatagramPacket
- 建立发送端,接收端(没有服务端和客户端概念
- 发送数据前,建立数据包/报 DatagramPacket对象
- 调用DatagramSocket的发送方法,接受方法
- 关闭DatagramSocket
package wjx.com.socket.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPSender {
public static void main(String[] args) throws IOException {
// 创建DatagramSocket对象,在9998端口接收数据
DatagramSocket socket = new DatagramSocket(9998);
// 封装的 DatagramPacket 对象 bytes内容字节数组 , bytes.length , 主机(IP) , 端口
byte[] bytes = "hello,明天吃火锅".getBytes();
DatagramPacket packet
= new DatagramPacket(bytes,0,bytes.length, InetAddress.getByName("192.168.10.9"),9999);
socket.send(packet);
byte[] bytes1 = new byte[1024];
DatagramPacket packet1 = new DatagramPacket(bytes1, bytes1.length);
socket.receive(packet1);
int length = packet1.getLength();
byte[] data = packet1.getData();
String str = new String(data, 0, length);
System.out.println(str);
socket.close();
System.out.println("B端退出");
}
}
/*
好的
B端退出
package wjx.com.socket.UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDPServer {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(9999);
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
//3. 调用 接收方法, 将通过网络传输的 DatagramPacket 对象
// 填充到 packet 对象
//当有数据包发送到 本机的 9999 端口时,就会接收到数据
// 如果没有数据包发送到 本机的 9999 端口, 就会阻塞等待
System.out.println("A端等待接收数据");
socket.receive(packet);
// 拆包
int length = packet.getLength();
byte[] data = packet.getData();
String str = new String(data, 0, length);
System.out.println(str);
System.out.println("A端退出");
byte[] bytes1 = "好的".getBytes();
DatagramPacket packet1 =
new DatagramPacket(bytes1, bytes1.length, InetAddress.getByName("192.168.10.9"),9998);
socket.send(packet1);
socket.close();
}
}
/*
A端等待接收数据
hello,明天吃火锅
A端退出
7.TCP文件下载
流程:
- 客户端向端口传输需要下载的文件名
- 服务端接听文件名
- 寻找磁盘中是否有该文件,如果有,则使用该文件,没有则使用默认文件
- 将得到的文件转换为字节数组
- 将字节数组放到数据通道中
- 客户端拿到字节数组
- 创建和文件关联的输出流,将字节数组输出到文件
服务端
package wjx.com.socket.FileLoad;
import wjx.com.socket.TCP.Utils_IO;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_1 {
public static void main(String[] args) throws IOException {
// 监听端口
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端等待连接");
// 得到连接
Socket socket = serverSocket.accept();
// 输入流,读取用户要下载的文件名
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = 0;
String loadFileName = "";
while ((len=inputStream.read(bytes))!=-1){
loadFileName += new String(bytes, 0, len);
}
System.out.println("申请下载的文件名为:"+loadFileName);
// 判断是否为grils.png 是则为grils.png 若不是,则设为默认的ikun.png
String str = "";
if("girl".equals(loadFileName)){
str = "src\\girl.png";
}else{
str = "src\\ikun.png";
}
// 得到文件的字节数组
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(str));
ByteArrayOutputStream bao = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int readlen = 0;
while((readlen=bis.read(b))!=-1){
bao.write(b, 0, readlen);
}
byte[] buf = bao.toByteArray();
bao.close();
// 将文件字节数组写入通道
BufferedOutputStream bos =
new BufferedOutputStream(socket.getOutputStream());
bos.write(buf);
socket.shutdownOutput();
// 关闭资源
serverSocket.close();
socket.close();
inputStream.close();
bis.close();
bos.close();
System.out.println("服务端关闭");
}
}
package wjx.com.socket.FileLoad;
import wjx.com.socket.TCP.Utils_IO;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client_1 {
public static void main(String[] args) throws IOException {
// 获得用户需要下载的资源
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你想要下载的资源:");
String fileName = scanner.next();
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream();
outputStream.write(fileName.getBytes());
socket.shutdownOutput();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
ByteArrayOutputStream bao = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int readlen = 0;
while((readlen=bis.read(b))!=-1){
bao.write(b, 0, readlen);
}
byte[] buf = bao.toByteArray();
bao.close();
String filepath = "src\\"+fileName+".png";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filepath));
bos.write(buf);
socket.close();
outputStream.close();
bis.close();
bos.close();
System.out.println("客户端退出");
}
}