Java网络编程

学习内容:

  1. 什么是计算机网络
  2. 网络通信的两个要素
  3. IP地址
  4. 端口Port
  5. 通信协议
  6. TCP实现聊天
  7. TCP文件上传实现
  8. UDP消息发送
  9. UDP聊天实现
  10. UDP在线咨询
  11. URL

学习笔记:

1.什么是计算机网络

概念:
指将地理位置不同的具有 独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统网络管理软件网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统

网络编程的目的:
传播交流信息,数据交换,进行通信等。

两个问题:

  1. 如何准确的定位网络上的一台或者多台主机
  2. 找到主机之后如何进行通信

Javaweb: 网页编程 B/S
网络编程:TCP/IP C/S

2.网络通信的要素

如何实现网络的通信?

1.通信双方的地址:

  • ip
  • 端口号

2.规则:网络通信的协议
TCP/IP模型:
在这里插入图片描述

3.IP地址

IP地址:InetAddress

  • 唯一定位一台网络上计算机
  • 本机localhost
  • IP地址的分类:
    • ipv4/ipv6
      • IPV4 127.0.0.1 ,4个直接组成 ,0~255 , 42亿,三十e在北美,四e在亚洲。2011年就用尽;
      • IPV6 fe80:915d:470e:d522:4339:fe4d:db39:1984,写成8个无符号整数,每个整数用四个十六进制位表示,
    • 公网-私网
      公网地址(万维网使用)和私有地址(局域网使用)。
      192.168.开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用。
  • 域名:记忆IP问题
    • IP:www.baidu.com
package com.bilibili;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class TestInetAdress {

	public static void main(String[] args) {
		try {
			//查询本机地址
			InetAddress inetAddress1= InetAddress.getByName("127.0.0.1");
			System.out.println(inetAddress1);
			InetAddress inetAddress3= InetAddress.getByName("localhost");
			System.out.println(inetAddress1);
			InetAddress inetAddress4= InetAddress.getLocalHost();
			System.out.println(inetAddress4);
			
			
			//查询网站ip地址
			InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
			System.out.println(inetAddress2);
			
			//常用方法
			System.out.println(inetAddress2.getAddress());
			System.out.println(inetAddress2.getCanonicalHostName());//规范名字
			System.out.println(inetAddress2.getHostAddress());//ip
			System.out.println(inetAddress2.getHostName());//域名,或者自己电脑的名字
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

	}

}

输出结果:

/127.0.0.1
/127.0.0.1
Wym-forever2003/192.168.137.1
www.baidu.com/39.156.66.18
[B@1055e4af
39.156.66.18
39.156.66.18
www.baidu.com

4.端口Port

  • 不同的进程有不同的端口号!用来区分软件!
  • 端口号标识正在计算机上运行的进程(程序)。
  • 被规定为一个 16 位的整数 0~65535。
  • 端口分类:
    • 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
    • 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
    • 动态/私有端口:49152~65535。
  • 端口号与IP地址的组合得出一个网络套接字:Socket。
  • 使用Socket注意事项:
    • 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
    • 通信的两端都要有Socket,是两台机器间通信的端点。
    • 网络通信其实就是Socket间的通信。
    • Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
    • 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
      网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
package com.bilibili;

import java.net.InetSocketAddress;

public class TestInetSocketAdress {

	public static void main(String[] args) {
	InetSocketAddress SocketAddress = new InetSocketAddress("127.0.0.1",8080);
	InetSocketAddress SocketAddress2 = new InetSocketAddress("localhost",8080);

		System.out.println(SocketAddress);
		System.out.println(SocketAddress2);
		
		System.out.println(SocketAddress.getAddress());
		System.out.println(SocketAddress.getHostName());
		System.out.println(SocketAddress.getPort());
	}

}

输出结果:

/127.0.0.1:8080
localhost/127.0.0.1:8080
/127.0.0.1
127.0.0.1
8080

5.通信协议

TCP通信协议
传输控制协议 (Transmission Control Protocol)

  • TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过"三次握手”
  • 三次握手: TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
    • 第一次握手:客户端向服务器端发出连接请求,等待服务器确认
    • 第二次握手:服务器端向客户端回送一个响应, 通知客户端收到了连接请求
    • 第三次握手:客户端再次向服务器端发送确认信息,确认连接
  • 完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如.上传文件、下载文件、 浏览网页等
    UDP协议
    用户数据报协议(User Datagram Protocol)
  • UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
    由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
  • 例如视频会议通常采用UDP协议, 因为这种情况即使偶尔丢失一两个数据包, 也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。

6.TCP实现聊天

服务端:

package com.bilibili;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpDemo01 {

	public static void main(String[] args) throws Exception {
		
			//1.我有一个地址
			ServerSocket serverSocket = new ServerSocket(9999);
			//2.等待客户端连接过来
			Socket socket  = serverSocket.accept();
			//3.读取客户端的消息
			InputStream is = socket.getInputStream();
			//管道流
			ByteArrayOutputStream baos  = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len;
			while ((len=is.read(buffer)) != -1) {
				baos.write(buffer,0,len);
			}
			System.out.println(baos.toString());
			if (baos != null) {
			baos.close();
			is.close();
			socket.close();
			serverSocket.close();
			}			
		}
	}



客户端:

package com.bilibili;

import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class TcpDemo02 {

	public static void main(String[] args) throws Exception {
		
				//1.知道服务器的地址
				InetAddress serverIP = InetAddress.getByName("127.0.0.1");
				//2.端口号
				int port = 9999;
				//3.创建一个socket连接
				Socket socket = new Socket(serverIP,port);
				//4.发送消息
				OutputStream os = socket.getOutputStream();
				os.write("你好世界".getBytes());
				os.close();
				socket.close();
				
		
	}
}

输出结果

你好世界

7.TCP文件上传实现

服务器端:

package com.bilibili;

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 TcpDemo03 {

	public static void main(String[] args) throws Exception {
	    //创建服务
		ServerSocket serverSocket = new ServerSocket(9000);
		//监听客户端的连接
		Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接
		//获取输入流
		InputStream is = socket.getInputStream();
		//文件输出
		FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
		byte[] buffer = new byte[1024];
		int len;
		while ((len = is.read(buffer)) != -1) {
			fos.write(buffer,0,len);
		}
		
		//通知客户端接收完毕
		OutputStream os = socket.getOutputStream();
		os.write("我接受到了~".getBytes());
		//关闭资源
		fos.close();
		is.close();
		socket.close();
		serverSocket.close();
	}

}

客户端:

package com.bilibili;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class TcpDemo04 {

	public static void main(String[] args) throws Exception, Exception {
		// 创建一个连接
		Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
		//  创建一个输出流
		OutputStream os = socket.getOutputStream();
		//  文件流
		FileInputStream fis = new FileInputStream(new File("C:\\Users\\Lenovo\\Pictures\\Camera Roll\\底图.jpg"));
		//  写出文件
		byte[] buffer = new byte[1024];
		int len;
		while ((len=fis.read(buffer)) != -1){
			os.write(buffer,0,len);
		}
		//通知服务器,我已经完毕
		socket.shutdownOutput();
		
		
		//确定服务器接收完毕,才可以断开连接
		InputStream inputStream = socket.getInputStream();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer2 = new byte [2014];
		int len2;
		while ((len2 = inputStream.read(buffer2)) != -1) {
			baos.write(buffer2,0,len2);
		}
		System.out.println(baos.toString());
		//  关闭资源
		baos.close();
		inputStream.close();
		fis.close();
		os.close();
		socket.close();
	}

}

输出结果

有两个结果:
首先是控制台:
我接受到了~
然后是在stady文件夹下面
有一个receive.jpg文件
其内容和底图.jpg一样。

8.UDP消息发送

发送端

package com.bilibili;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpDemo01 {
//不需要连接服务器
	public static void main(String[] args) throws Exception {
		//建立一个socket
		DatagramSocket socket = new DatagramSocket();
		//建一个包
		String msg = "你好,服务器!";
		InetAddress localhost=InetAddress .getByName("localhost");
		int port = 8080;
		DatagramPacket packet= new DatagramPacket(msg.getBytes(), 0,msg.getBytes().length,localhost,port);
		//发送包
		socket.send(packet);
		//关闭流
		socket.close();
	}

}

接收端

package com.bilibili;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpDemo02 {

	public static void main(String[] args) throws Exception {
		// 开放端口
		DatagramSocket socket = new DatagramSocket(8080);
		//接收数据包
		byte[] buffer = new byte[1024];
		DatagramPacket packet = new DatagramPacket(buffer, 0,buffer.length);
	
		socket.receive(packet);//阻塞接收
		
		System.out.println(packet.getAddress().getHostAddress());
		System.out.println(new String(packet.getData(),0,packet.getLength()));
		//关闭连接
		socket.close();
		

	}

}

输出结果:

127.0.0.1
你好,服务器!

9.UDP聊天实现

发送端:

package com.Chart;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.channels.DatagramChannel;

public class UdpDemo01 {

	public static void main(String[] args) throws Exception {
		DatagramSocket socket = new  DatagramSocket(8888);
		
		//准备数据
		 BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
		 while (true) {
			 String data = reader.readLine();
			 byte[] datas = data.getBytes();
			 DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost", 6666));
			 
			 socket.send(packet);
			 if(data.trim().equals("bye")) {
				 break;
			 }
	}
		 socket.close();
	}
}


接收端:

package com.Chart;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UpdDemo02 {

	public static void main(String[] args)throws Exception {
	DatagramSocket Socket = new DatagramSocket(6666);
	
	
		while (true) {
			
			//准备接收包裹
			byte[] container = new byte[1024];
			DatagramPacket packet = new DatagramPacket(container,0,container.length);
			Socket.receive(packet);//阻塞式接收包裹
			
			//断开连接
			byte[] date = packet.getData();
			String receivedata = new String(date,0,date.length);
			
			System.out.println(receivedata);
			
			if(receivedata.trim().equals("bye")) {
				break;
			}
		}
	
	
	}

}

输出结果:
在这里插入图片描述
在这里插入图片描述

10.UDP在线咨询

接收端:

public class TalkReceive implements Runnable {
    DatagramSocket socket;
    private String msgFrom;

    public TalkReceive(int port, String msgFrom) throws SocketException {
        this.msgFrom = msgFrom;
        socket = new DatagramSocket(port);
    }

    @Override
    public void run() {
        try {
            while (true) {
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
                socket.receive(packet);
                byte[] data = packet.getData();
                String datas = new String(data, 0, packet.getLength());
                System.out.println(this.msgFrom + ":" + datas);
                if (datas.equals("bye")) {
                    socket.close();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}


发送端:

public class TalkSend implements Runnable {
    DatagramSocket socket;
    BufferedReader reader;
    private String toIp;
    private int toPort;

    public TalkSend(int fromPort, String toIp, int toPort) throws SocketException {
        this.toIp = toIp;
        this.toPort = toPort;
        socket = new DatagramSocket(fromPort);
        reader = new BufferedReader(new InputStreamReader(System.in));
    }

    @Override
    public void run() {
        try {
            while(true) {
                //从控制台读取信息
                byte[] bytes = reader.readLine().getBytes();
                //创建数据包
                DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIp, this.toPort));
                socket.send(packet);
                //退出循环
                if (new String(bytes).equals("bye")) {
                    socket.close();
                    reader.close();
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

启动:

public class TalkTeacher {
    public static void main(String[] args) throws SocketException {
        String host = "localhost";
        new Thread(new TalkSend(9999,host,8888)).start();
        new Thread(new TalkReceive(9000,"学生")).start();
    }
}

public class TalkStudent {
    public static void main(String[] args) throws SocketException {
        String host = "localhost";
        //开启两个线程,既可以发送又可以接收
        new Thread(new TalkSend(8000,host,9000)).start();
        new Thread(new TalkReceive(8888,"老师")).start();
    }
}

11.URL

package com.bilibili;

import java.net.URL;

public class URLDemo01 {

	public static void main(String[] args)throws Exception {
		URL url = new URL("https://blog.csdn.net/Lalune_YM/article/details/125548469?spm=1001.2014.3001.5501");
		
		System.out.println(url.getProtocol());//协议
		System.out.println(url.getHost());//主机ip
		System.out.println(url.getPort());//端口
		System.out.println(url.getPath());//文件
		System.out.println(url.getFile());//全路径
		System.out.println(url.getQuery());//参数
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值