Day22(面向网络编程)学习笔记(面向网络编程 UDP协议 TCP协议)

大纲

Day22(面向网络编程)学习目标

【学习目标】理解、了解、应用、记忆

通过今天的学习,参训学员能够:(解释的时候说出二级目标的掌握程度)

  1. 【应用】面向网络编程概述
  1. 【理解】能够独立阐述IP地址的作用
  2. 【理解】能够阐述端口号的作用
  3. 【理解】能够阐述协议的作用
  1. 【理解】UDP协议
  1. 【应用】能够独立完成UDP协议的发送端 
  2. 【应用】能够独立完成UDP协议的接收端
  1. 【理解】TCP协议

a.   【应用】 能够独立完成TCP协议的发送端

  1.  【应用】 能够独立完成TCP协议的接收端
  2.  【应用】 能够独立完成TCP协议的案例

收获

一 网络编程概述

二UDP协议

DatagramPacket数据包的作用就如同是“集装箱”,可以将发送端或者接收端的数据封装起来。然而运输货物只有“集装箱”是不够的,还需要有码头。在程序中需要实现通信只有DatagramPacket数据包也同样不行,为此JDK中提供的一个DatagramSocket类。DatagramSocket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包,发送数据的过程如下图所示。

                                          

发送数据

 package com.itheima_02;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
 * 使用UDP协议发送数据
		创建发送端Socket对象
		创建数据并打包
		发送数据
		释放资源
 * 
 * DatagramSocket:此类表示用来发送和接收数据,基于UDP协议的
 * 
 * DatagramSocket() :创建Socket对象并随机分配端口号
 * DatagramSocket(int port) :创建Socket对象并指定端口号
 */
public class SendDemo {
	public static void main(String[] args) throws IOException  {
		//创建发送端Socket对象
		DatagramSocket ds = new DatagramSocket();
		//创建数据并打包
		/*
		 * DatagramPacket :此类表示数据报包
		 * 数据 byte[]
		 * 设备的地址 ip
		 * 进程的地址  端口号
		   DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
		 */
		
		String s = "hello udp,im comming!";
		byte[] bys = s.getBytes();
		int length = bys.length;
		InetAddress address = InetAddress.getByName("itheima");//发送给当前设备
		int port = 8888;
		//打包
		DatagramPacket dp = new DatagramPacket(bys,length,address,port);
		//发送数据
		ds.send(dp);
		//释放资源
		ds.close();
	}
}

接收数据

package com.itheima_02;

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

/*
 * 使用UDP协议接收数据
		创建接收端Socket对象
		接收数据
		解析数据
		输出数据
		释放资源

 */
public class ReceiveDemo {
	public static void main(String[] args) throws IOException {
		//创建接收端Socket对象
		DatagramSocket ds = new DatagramSocket(8888);
		//接收数据
		//DatagramPacket(byte[] buf, int length) 
		byte[] bys = new byte[1024];
		DatagramPacket dp = new DatagramPacket(bys,bys.length);
				
		System.out.println(1);
		ds.receive(dp);//阻塞
		System.out.println(2);
		
		//解析数据
		//InetAddress getAddress() : 获取发送端的IP对象
		InetAddress address = dp.getAddress();
		//byte[] getData()  :获取接收到的数据,也可以直接使用创建包对象时的数组
		byte[] data = dp.getData();
		//int getLength()  :获取具体收到数据的长度
		int length = dp.getLength();
		
		
		
		//输出数据
		System.out.println("sender ---> " + address.getHostAddress());
		//System.out.println(new String(data,0,length));
		System.out.println(new String(bys,0,length));
		//释放资源
		ds.close();

	}
}

TCP协议

在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端。

接下来通过一张图来描述服务器端和客户端的数据传输,如下图所示。

                                         

发送数据

package com.itheima_04;

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

/*
 * 使用TCP协议发送数据
		创建发送端Socket对象(创建连接)
		获取输出流对象
		发送数据
		释放资源
		
	Socket(InetAddress address, int port) 
	Exception in thread "main" java.net.ConnectException: Connection refused: connect

 */
public class ClientDemo {
	public static void main(String[] args) throws IOException {
		//创建发送端Socket对象(创建连接)
		Socket s = new Socket(InetAddress.getByName("itheima"),10086);
		//获取输出流对象
		OutputStream os = s.getOutputStream();
		//发送数据
		String str = "hello tcp,im comming!!!";
		os.write(str.getBytes());
		//释放资源
		//os.close();
		s.close();
	}
}

接收数据

package com.itheima_04;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 使用TCP协议接收数据
 		创建接收端Socket对象
 		监听(阻塞)
 		获取输入流对象
 		获取数据
 		输出数据
 		释放资源
 		
 	ServerSocket:接收端,服务端Socket
 	ServerSocket(int port) 
 	Socket accept() 
 
 */
public class ServerDemo {
	public static void main(String[] args) throws IOException  {
		//创建接收端Socket对象
		ServerSocket ss = new ServerSocket(10086);
 		//监听(阻塞)
		Socket s = ss.accept();
 		//获取输入流对象
		InputStream is = s.getInputStream();
 		//获取数据
		byte[] bys = new byte[1024];
		int len;//用于存储读到的字节个数
		len = is.read(bys);
 		//输出数据
		InetAddress address = s.getInetAddress();
		System.out.println("client ---> " + address.getHostName());
		System.out.println(new String(bys,0,len));
 		//释放资源
		s.close();
		//ss.close();
	}
}

案例代码

 将用户名和密码封装到一个User类中,提供对应的构造方法和getter/setter方法

 新建一个UserDB类里面定义一个集合,在集合中添加以下User对象

new User("zhangsan","123456");

 new User("lisi","654321");

 new User("itheima","itheima");

 new User("admin","password");

 客户端:

1.提示用户输入用户名和密码,将用户输入的用户名和密码发送给服务端

2.接收服务端验证完用户名和密码的结果

 服务端:

1.服务端将客户端发送过来的用户名密码封装成User对象

2.集合中如果包括这个User对象,想客户端写入” 登录成功”

              否则向客户端写入”登录失败”

客户端

package com.itheima_07;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/*
 * 模拟用户登录改写(面向对象版本)
 */
public class ClientTest {
	public static void main(String[] args) throws  IOException  {
		//创建客户端Socket对象
		Socket s = new Socket("itheima",8888);
		
		//获取用户名和密码
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("请输入用户名:");
		String username = br.readLine();
		System.out.println("请输入密码:");
		String password = br.readLine();
		
		
		//获取输出流对象
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		//写出数据
		out.println(username);
		out.println(password);
		
		//获取输入流对象
		BufferedReader serverBr = new BufferedReader(new InputStreamReader(s.getInputStream()));
		//获取服务器返回的数据
		String result = serverBr.readLine();
		System.out.println(result);
		//释放资源
		s.close();
	}
}

服务器端

package com.itheima_07;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

public class ServerTest {
	public static void main(String[] args) throws IOException {
		//创建服务器端Socket对象
		ServerSocket ss = new ServerSocket(8888);
		//监听
		Socket s = ss.accept();
		//获取输入流对象
		BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
		//获取用户名和密码
		String username = br.readLine();
		String password = br.readLine();
		//判断用户名和密码是否正确
		boolean flag = false;
	
		/*if("itheima".equals(username) && "123456".equals(password)) {
			flag = true;
		}*/
		
		List<User> users = UserDB.getUsers();
		User user = new User(username,password);
		if(users.contains(user)) {
			//匹配成功
			flag = true;
		}
		
		
		//获取输出流对象
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		
		//返回判断信息
		if(flag) {
			out.println("登陆成功");
		}
		else {
			out.println("登陆失败");
		}
		//释放资源
		s.close();
		//ss.close();//服务器一般不关闭
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值