day26(网络编程) & TCPUDP & DatagramPacket & DatagramSocket & Socket & ServerSocket笔记

本文详细介绍了计算机网络的概念,网络编程的基本要素包括IP地址、端口号和协议,重点讲解了UDP和TCP协议的特点,以及如何使用Socket进行网络通信。通过实例演示了UDP和TCP的编程过程,包括客户端和服务端的交互方式,特别强调了多线程在服务端的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

26.01_网络编程(网络编程概述)(了解)

  • A:计算机网络

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

    • 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

26.02_网络编程(网络编程三要素之IP概述)(掌握)

  • 每个设备在网络中的唯一标识
  • 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
  • ipconfig:查看本机IP
  • ping:测试连接是否成功
  • 本地回路地址:127.0.0.1 (自己给自己发送数据)
  • 255.255.255.255是广播地址
  • IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
  • IPv6:8组,每组4个16进制数。前后0000只能一次省略一处
  • 1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
  • 1a2b::aaaa:0000:0000:0000:aabb:1f2f
  • 1a2b:0000:aaaa::aabb:1f2f
  • 1a2b:0000:aaaa::0000:aabb:1f2f
  • 1a2b:0000:aaaa:0000::aabb:1f2f

26.03_网络编程(网络编程三要素之端口号概述)(掌握)

  • 每个程序在设备上的唯一标识
  • 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。
  • 端口号范围从0-65535
  • 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
  • 常用端口
    • mysql: 3306
    • oracle: 1521
    • web: 80
    • tomcat: 8080
    • QQ: 4000
    • feiQ: 2425

26.04_网络编程(网络编程三要素协议)(掌握)

  • 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
  • UDP

    • 面向无连接,数据不安全,速度快。不区分客户端与服务端。
  • TCP

* 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
* 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据

# 26.05_网络编程(Socket通信原理图解)(了解)

  • A:Socket套接字概述:
    • 网络上具有唯一标识的IP地址端口号组合在一起才能构成唯一能识别的标识符套接字。
    • 通信的两端都有Socket。
    • 网络通信其实就是Socket间的通信。
    • 数据在两个Socket间通过IO流传输。
    • Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。

26.06_网络编程(UDP传输)(了解)

  • 1.发送Send

    • 创建DatagramSocket, 随机端口号

    • 创建DatagramPacket, 指定数据, 长度, 地址, 端口

    • 使用DatagramSocket发送DatagramPacket

    • 关闭DatagramSocket

        public static void main(String[] args) throws Exception {
        		String str = "what are you 弄啥呢?";
        		DatagramSocket socket = new DatagramSocket();	//创建Socket相当于创建码头
        		DatagramPacket packet =
        			new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);    //创建Packet相当于集装箱
        		socket.send(packet);	//发货,将数据发出去
        		socket.close();		//关闭码头
        	}
      
  • 2.接收Receive

    • 创建DatagramSocket, 指定端口号

    • 创建DatagramPacket, 指定数组, 长度

    • 使用DatagramSocket接收DatagramPacket

    • 关闭DatagramSocket

    • 从DatagramPacket中获取数据

        public static void main(String[] args) throws Exception {
        	DatagramSocket socket = new DatagramSocket(6666);		//创建Socket相当于创建码头
        	DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);	//创建Packet相当于创建集装箱
        	socket.receive(packet);		//接货,接收数据
        	
        	byte[] arr = packet.getData();	 //获取数据
        	int len = packet.getLength();	 //获取有效的字节个数
        	System.out.println(new String(arr,0,len));
        	socket.close();
      
  • 3.接收方获取ip和端口号

    • String ip = packet.getAddress().getHostAddress();
    • int port = packet.getPort();

# 26.07_网络编程(UDP传输优化)

  • 接收端Receive

  •   DatagramSocket socket = new DatagramSocket(6666);			//创建socket相当于创建码头
      DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);		//创建packet相当于创建集装箱
      
      while(true) {
      	socket.receive(packet);			//接收货物
      	byte[] arr = packet.getData();
      	int len = packet.getLength();
      	String ip = packet.getAddress().getHostAddress();
      	System.out.println(ip + ":" + new String(arr,0,len));
      }
    
  • 发送端Send

      DatagramSocket socket = new DatagramSocket();		//创建socket相当于创建码头
      Scanner sc = new Scanner(System.in);
      
      while(true) {
      	String str = sc.nextLine();		//获取键盘录入的字符串
      	if("quit".equals(str))
      		break;
      	DatagramPacket packet = 							//创建packet相当于创建集装箱
      			new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
      	socket.send(packet);			//发货
      }
      socket.close();
    

26.08_网络编程(UDP传输多线程)

  • A发送和接收在一个窗口完成

      	/**
      	 * @param args
      	 */
      	public static void main(String[] args) {
      		new Receive().start();
      		
      		new Send().start();
      	}
      
      }
      
      class Receive extends Thread {
      	public void run() {
      		try {
      			DatagramSocket socket = new DatagramSocket(6666);		//创建Socket相当于创建码头
      			DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);    //创建Packet相当于创建集装箱
      			
      			while(true) {
      				socket.receive(packet);	  //接货,接收数据
      				
      				byte[] arr = packet.getData();    //获取数据
      				int len = packet.getLength();	//获取有效的字节个数
      				String ip = packet.getAddress().getHostAddress();	//获取ip地址
      				int port = packet.getPort();	//获取端口号
      				System.out.println(ip + ":" + port + ":" + new String(arr,0,len));
      			}
      		} catch (IOException e) {
      			
      			e.printStackTrace();
      		}
      	}
      }
      
      class Send extends Thread {
      	public void run() {
      		try {
      			Scanner sc = new Scanner(System.in);						//创建键盘录入对象
      			DatagramSocket socket = new DatagramSocket();		//创建Socket相当于创建码头
      			
      			while(true) {
      				String line = sc.nextLine();	//获取键盘录入的字符串
      				if("quit".equals(line)) {
      					break;
      				}
      				DatagramPacket packet = 		//创建Packet相当于集装箱
      						new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
      				socket.send(packet);	 //发货,将数据发出去
      			}
      			socket.close();
      		}  catch (IOException e) {
      			
      			e.printStackTrace();
      		}		
      	}
    

26.16_网络编程(TCP协议)(掌握)

  • 1.客户端

    • 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器

    • 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流

    • 输入流可以读取服务端输出流写出的数据

    • 输出流可以写出数据到服务端的输入流

        public static void main(String[] args) throws UnknownHostException, IOException {
        	Socket socket = new Socket("127.0.0.1", 12345);
        	
        	InputStream is = socket.getInputStream();			//获取客户端输入流
        	OutputStream os = socket.getOutputStream();			//获取客户端的输出流
        	
        	byte[] arr = new byte[1024];
        	int len = is.read(arr);			//读取服务器发过来的数据
        	System.out.println(new String(arr,0,len));       	//将数据转换成字符串并打印
        	
        	os.write("学习挖掘机哪家强?".getBytes());	//客户端向服务器写数据
        	
        	socket.close();
        }
      
  • 2.服务端

    • 创建ServerSocket(需要指定端口号)

    • 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket

    • 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流

    • 输入流可以读取客户端输出流写出的数据

    • 输出流可以写出数据到客户端的输入流

        public static void main(String[] args) throws IOException {
        	ServerSocket server = new ServerSocket(12345);
        	
        	Socket socket = server.accept();	//接受客户端的请求
        	InputStream is = socket.getInputStream();			//获取客户端输入流
        	OutputStream os = socket.getOutputStream();			//获取客户端的输出流
        	
        	os.write("百度一下你就知道".getBytes());	//服务器向客户端写出数据
        	
        	byte[] arr = new byte[1024];
        	int len = is.read(arr);		//读取客户端发过来的数据
        	System.out.println(new String(arr,0,len));       	//将数据转换成字符串并打印
        	
        	socket.close();
        }
      

26.17_网络编程(TCP协议代码优化)

  • 客户端

      public static void main(String[] args) throws UnknownHostException, IOException {
      	Socket socket = new Socket("127.0.0.1", 12345);
      	BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));		//将字节流包装成了字符流
      	PrintStream ps = new PrintStream(socket.getOutputStream());		//PrintStream中有写出换行的方法
      	
      	System.out.println(br.readLine());
      	ps.println("我想报名黑马程序员");
      	System.out.println(br.readLine());
      	ps.println("大哭!!!能不能给次机会");
      	
      	socket.close();
      }
    
  • 服务端

      public static void demo1() throws IOException {
      	ServerSocket server = new ServerSocket(12345);
      	
      	Socket socket = server.accept();		//接受客户端的请求
      	
      	BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));		//将字节流包装成了字符流
      	PrintStream ps = new PrintStream(socket.getOutputStream());			//PrintStream中有写出换行的方法
      	
      	ps.println("欢迎咨询黑马程序员");
      	System.out.println(br.readLine());
      	ps.println("不好意思,爆满了");
      	System.out.println(br.readLine());
      	socket.close();
      }
    

26.18_网络编程(服务端是多线程的)(掌握)

ServerSocket server = new ServerSocket(9999);	//创建服务器
	while(true) {
		final Socket socket = server.accept();				//接受客户端的请求
		new Thread() {
			public void run() {
				try {
					BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));	//将字节流包装成了字符流
					PrintStream ps = new PrintStream(socket.getOutputStream());		//PrintStream中有写出换行的方法
					ps.println("欢迎咨询传智播客");
					System.out.println(br.readLine());
					ps.println("报满了,请报下一期吧");
					System.out.println(br.readLine());
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}
}

26.19_网络编程:客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串

	//客户端
	public class Test1_Client {

	/**
	 * 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args) throws UnknownHostException, IOException {
		Scanner sc = new Scanner(System.in);				//创建键盘录入对象
		Socket socket = new Socket("129.0.0.1", 54321);		//创建客户端,指定ip地址和端口号
		
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));	//获取输入流
		PrintStream ps = new PrintStream(socket.getOutputStream());//获取输出流
		
		ps.println(sc.nextLine());							//将字符串写到服务器去
		System.out.println(br.readLine()); 					//将反转后的结果读出来
		
		socket.close();
	}

	}
	//服务器端
	public class Test1_Server {
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		ServerSocket server = new ServerSocket(54321);
		System.out.println("服务器启动,绑定54321端口");
		
		while(true) {
			final Socket socket = server.accept();					//接受客户端的请求
			
			new Thread() {											//开启一条线程
				public void run() {
					try {
						BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));	//获取输入流
						PrintStream ps = new PrintStream(socket.getOutputStream());//获取输出流
						
						String line = br.readLine();				//将客户端写过来的数据读取出来
						line = new StringBuilder(line).reverse().toString();	//链式编程
						ps.println(line);							//反转后写回去
						
						socket.close();
					} catch (IOException e) {						
						
						e.printStackTrace();
					}
				}
			}.start();
		}
	}

	}

26.20_网络编程:客户端向服务器上传文件

	//客户端
	public class Test2_UpdateClient {
	/**
	 * @param args
	 * @throws IOException 
	 * @throws UnknownHostException 
	 */
	public static void main(String[] args) throws UnknownHostException, IOException {
		// 1.提示输入要上传的文件路径, 验证路径是否存在以及是否是文件夹
		File file = getFile();
		// 2.发送文件名到服务端
		Socket socket = new Socket("127.0.0.1", 12345);
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		PrintStream ps = new PrintStream(socket.getOutputStream());
		ps.println(file.getName());
		// 6.接收结果, 如果存在给予提示, 程序直接退出
		String result = br.readLine();						//读取存在后不存在的结果
		if("存在".equals(result)) {
			System.out.println("您上传的文件已经存在,请不要重复上传");
			socket.close();
			return;
		}
		// 7.如果不存在, 定义FileInputStream读取文件, 写出到网络
		FileInputStream fis = new FileInputStream(file);
		byte[] arr = new byte[8192];
		int len;
		
		while((len = fis.read(arr)) != -1) {
			ps.write(arr, 0, len);
		}
		
		fis.close();
		socket.close();
	}

	private static File getFile() {
		Scanner sc = new Scanner(System.in);				//创建键盘录入对象
		System.out.println("请输入一个文件路径:");
		
		while(true) {
			String line = sc.nextLine();
			File file = new File(line);
			
			if(!file.exists()) {
				System.out.println("您录入的文件路径不存在,请重新录入:");
			}else if(file.isDirectory()) {
				System.out.println("您录入的是文件夹路径,请输入一个文件路径:");
			}else {
				return file;
			}
		}
	}
	}

	//服务器端
	public class Test2_UpdateServer {
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		//3,建立多线程的服务器
		ServerSocket server = new ServerSocket(12345);
		System.out.println("服务器启动,绑定12345端口号");
		
		//4.读取文件名
		while(true) {
			final Socket socket = server.accept();					//接受请求
			new Thread() {
				public void run() {
					try {
						InputStream is = socket.getInputStream();
						BufferedReader br = new BufferedReader(new InputStreamReader(is));
						PrintStream ps = new PrintStream(socket.getOutputStream());
						String fileName = br.readLine();
						
						//5.判断文件是否存在, 将结果发回客户端
						File dir = new File("update");
						dir.mkdir();								//创建文件夹
						File file = new File(dir,fileName);			//封装成File对象
						
						if(file.exists()) {							//如果服务器已经存在这个文件
							ps.println("存在");						//将存在写给客户端
							socket.close();							//关闭socket
							return;
						}else {
							ps.println("不存在");
						}
						
						//8.定义FileOutputStream, 从网络读取数据, 存储到本地
						FileOutputStream fos = new FileOutputStream(file);
						byte[] arr = new byte[8192];
						int len;
						
						while((len = is.read(arr)) != -1) {
							fos.write(arr, 0, len);
						}
						
						fos.close();
						socket.close();
					} catch (IOException e) {
						
						e.printStackTrace();
					}
				}
			}.start();
		}
		
		
		
	}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值