网络编程
1、IP
ip地址: InetAddress
- 唯一定位一台网络上计算机.
- 127.0.0.1:本机 localhost
- ip地址的分类
- ipv4 / ipv6
- iPV4 127.0.0.1,64位,4个字节组成,0~255.
- iPV6 128位。8个无符号整数!
- 公网-私网
- ipv4 / ipv6
public static void main(String[] args) throws UnknownHostException {
//查询本机地址
InetAddress localHost1 = InetAddress.getLocalHost();
System.out.println(localHost1);
InetAddress localhost2 = InetAddress.getByName("localhost");
System.out.println(localhost2);
InetAddress localhost3 = InetAddress.getByName("127.0.0.1");
System.out.println(localhost3);
//查询网站IP地址
InetAddress baiduIp = InetAddress.getByName("www.baidu.com");
System.out.println(baiduIp);
//常用方法(了解)
System.out.println(baiduIp.getAddress());
System.out.println(baiduIp.getCanonicalHostName());//规范的名字
System.out.println(baiduIp.getHostAddress());//IP
System.out.println(baiduIp.getHostName());//域名或自己电脑的名字
}
2、端口
端口表示计算机上的一个程序的进程。
- 不同的进程有不同的端口号!用来区分软件!
- 被规定 0~65535
- TCP,UDP : 65535 2 tcp: 80,udp:80,单个协议下,端口号不能冲突*
- 端口分类
- 公有端口0~1023
- HTTP : 80
- HTTPS : 443
- FTP∶21
- Telent : 23
- 程序注册端口:1024~49151,分配用户或者程序
- Tomcat : 8080
- MySQL : 3306
- Oracle : 1521
- 动态、私有 : 49152~65535
- 常用指令
- netstat -ano 查看所有的端口
- netstat -ano| findstr "5900” #查看指定的端口
- tasklist|findstr “8696” #查看指定端口的进程
- ctrl+ shift + ESC 任务管理器
3、通信协议
协议 : 约定,就好比我们现在说的是普通话。
网络通信协议 : 速率,传输码率,代码结构,传输控制.……
TCP/IP协议簇 : 实际上是一组协议
重要 :
- TCP : 用户传输协议
- UDP : 用户数据报协议
知名 :
- TCP 、IP 协议
4、TCP
客户端
1.连接服务器Socket(需要 InetAddress,port[端口号])
2.发送消息 (Socket 获取文件流)
服务器
1.建立服务的端口(ServerSocket(inetAddress[不写默认为本地] ,端口号))
2.等待用户的链接 (accept)
3.接收用的消息(Socket 获取文件流)
例子1、消息传输
例子2、文件传输
(1)客户端
public static void main(String[] args) throws Exception {
//1、创建一个 socket 连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9999);
//2、创建一个输出流
OutputStream os = socket.getOutputStream();
//3、读取文件
FileInputStream fis = new FileInputStream(new File("G:\\JavaCode\\NetTest\\src\\l1.jpg"));
//4、写出文件
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer))!=-1){
os.write(buffer,0, len);
}
//通知服务器我传输完了
socket.shutdownOutput();
//确定服务器接收完毕,才能断开连接[服务器通知我,我接受服务器的通知消息]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = socket.getInputStream();
byte[] buffer1 = new byte[1024];
int len1;
while ((len1 = is.read(buffer1))!=-1){
baos.write(buffer1,0,len1);
}
System.out.println(baos.toString());
//5、关闭资源
is.close();
baos.close();
fis.close();
os.close();
socket.close();
}
(1)服务端
public static void main(String[] args) throws Exception {
//1、创建服务
ServerSocket serverSocket = new ServerSocket(9999);
//2、监听客户端的连接
Socket accept = serverSocket.accept();
//3、获取输入流
InputStream is = accept.getInputStream();
//4、文件输出(存放)
FileOutputStream fos = new FileOutputStream("G:\\JavaCode\\NetTest\\src\\l2.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户端接收完毕
OutputStream os = accept.getOutputStream();
os.write("服务器对客户端说:我接收完毕了,你可以断开连接了!".getBytes());
//5、关闭资源
os.close();
fos.close();
is.close();
accept.close();
serverSocket.close();
}
5、UDP
发短信: 不用连接,需要知道对方的地址! 且服务端和客户端的角色定位不再那么清晰了。服务端与客户端有成为另一种角色的可能。
客户端
1.建立一个DatagramSocket
2.确定要发送的消息、发给谁。(inetAddress,port)
3.创建数据包 datagramPacket
4.发送包 datagramSocket.send(datagramPacket);
5.关闭连接
服务器
1.建立一个DatagramSocket(端口号),开放端口
2.创建数据包 datagramPacket
3.接收数据包 datagramSocket.receive(datagramPacket);
4.消息的处理
datagramPacket.getData() 获取内容
datagramPacket.getAddress() 获取地址等相关信息
5.关闭连接
例子1、消息发送
(1)客户端
public static void main(String[] args) throws Exception {
//1.建立一个DatagramSocket
DatagramSocket datagramSocket = new DatagramSocket();
//消息、发给谁
String msg = null;
Scanner scanner = new Scanner(System.in);
msg = scanner.next();
// String msg ="hello 服务器!";
byte[] buffer = msg.getBytes();
InetAddress inetAddress = InetAddress.getByName("localhost");
int port = 9090;
//2.创建包
DatagramPacket datagramPacket = new DatagramPacket(buffer,0 ,buffer.length,inetAddress,port );
//3.发送包
datagramSocket.send(datagramPacket);
//4.关闭连接
datagramSocket.close();
}
}
(2)服务/接收端
public static void main(String[] args) throws IOException {
//1.建立一个DatagramSocket,开放端口
DatagramSocket datagramSocket = new DatagramSocket(9090);
//2.数据包
byte[] buffer = new byte[1024];
while (true){
DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
//3.接收
datagramSocket.receive(datagramPacket);
//输出
System.out.println(datagramPacket.getAddress().getHostAddress());
System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));
//4.关闭连接
datagramSocket.close();
}
}
6、UDP实现聊天例子
就是让一个类同时拥有发送消息和接收消息的能力,要做到这一点就需要用到 多线程。发送消息和接收消息的能力则是线程任务。
1.发送消息实现
public class TalkSend implements Runnable{
DatagramSocket datagramSocket = null;
BufferedReader bufferedReader = null;
private Integer myPort;
private String toIP;
private Integer toPort;
//构造函数 进行一些初始化操作
public TalkSend(Integer myPort, String toIP, Integer toPort) {
this.myPort = myPort;
this.toIP = toIP;
this.toPort = toPort;
try {
datagramSocket = new DatagramSocket(myPort);
//准备数据,控制台读取 System.in
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
//准备包裹
String data = bufferedReader.readLine();
byte[] buffer = data.getBytes();
DatagramPacket dgp = new DatagramPacket(buffer, 0,buffer.length,new InetSocketAddress( this.toIP, this.toPort));
datagramSocket.send(dgp);
if (data.equals("结束会话")){break;}
}catch (Exception e){
e.printStackTrace();
}
//断开连接
datagramSocket.close();
}
}
}
2.接收消息实现
public class TalkReceive implements Runnable{
DatagramSocket datagramSocket = null;
private Integer port;
private String msgFrom;
//构造函数
public TalkReceive(Integer port, String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
datagramSocket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true){
try {
//2.接收数据包
byte[] buffer = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
datagramSocket.receive(datagramPacket);
//3.结束会话或输出
byte[] data = datagramPacket.getData();
String receiveData = new String(data,0,data.length);
System.out.println(this.msgFrom+":"+receiveData);
if (receiveData.equals("结束会话")){break;}
} catch (IOException e) {
e.printStackTrace();
}
}
//4.关闭连接
datagramSocket.close();
}
}
3.创建两个线程任务,获取发送和接收消息的功能
//用户1:
public class TalkOne {
public static void main(String[] args) {
System.out.println("你们现在可以开始来聊天了!");
System.out.println("如需结束,请输入结束会话");
new Thread(new TalkSend(7777, "localhost", 9999)).start();
new Thread(new TalkReceive(8888, "老师")).start();
}
}
//用户2:
public class TalkOther {
public static void main(String[] args) {
System.out.println("你们现在可以开始来聊天了!");
System.out.println("如需结束,请输入结束会话");
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999, "学生")).start();
}
}
注意:
- TalkSend 的 端口 对应另一个用户的 TalkReceive 端口。发送对应接收。
- TalkSend 的 5555、7777 还没看出有啥用,可能就是这个任务占用的端口。
7、URL
统一资源定位符:定位资源的,定位互联网上的某一个资源。
例子:下载图片
public static void main(String[] args) throws Exception {
String dwUrl = "https://pic.netbian.com/uploads/allimg/210429/111909-16196663494cca.jpg";
URL url = new URL(dwUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("H:\\文本\\1.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
fos.write(buffer,0,len);
}
fos.close();
inputStream.close();
httpURLConnection.disconnect();
}