黑马程序员_【总结】_ 网络编程知识梳理_(end)

时间:2023-02-19 16:13:18
网络编程知识梳理


---------- android培训 java培训、期待与您交流! ---------- 
--------------------------------------------------------------------------------------------------------------------------------------------- 1、InetAddress 用于获取 ip等信息
InetAddress i = InetAddress.getLocalHost();//获取---本机名称和地址 i.getHostAddress() 获取---本机地址 i.getHostName() 获取---本机名称
2、Socket: 通常所说的网络编程,数据通过两端的Socket 之间的IO进程传输
3、UDP(1、速度快 2、无连接    3、<= 64K包 4、不可靠)
4、UDP 通过DatagarmSocket   和     DatagramPacket   建立发送端和接收端
通过:send()---receive() 进行数据包的发送-接收
5、TCP (1、必须连接 2、大数据 3、可靠 4、效率稍低)
6、TCP 通过Socket    和    ServerSocket 建立服务端和客户端
7、shutdownOutput  【很关键的一步】: 指定 结束标记    相当于指定-1
8、当有多用户上传等相关类似情况时,定义上传功能为线程,通过循环接收不同的ip启动多个线程
---------------------------------------------------
【1】
1、找到对方IP
2、数据要发送到对方应用 指定的端口
3、通讯规则、协议   TCP/IP
InetAddress i = InetAddress.getLocalHost();//获取---本机名称和地址 i.getHostAddress() 获取---本机地址 i.getHostName() 获取---本机名称 InetAddress id = InetAddress.getByName("www.baidu.com");//返回的是  主机+IP的 数组转换为字符串打印:
class $1IPDemo 
{
public static void main(String[] args) throws Exception
{
InetAddress i = InetAddress.getLocalHost();//获取---本机名称和地址
System.out.println(i.toString());

System.out.println(i.getHostAddress());//获取---本机地址
System.out.println(i.getHostName());//获取---本机名称
sop("--------------------------");
InetAddress id = InetAddress.getByName("www.baidu.com");//返回的是 主机+IP的 数组转换为字符串打印:
sop(id.toString());
sop(id.getHostAddress());
sop(id.getHostName());
}
public static void sop(Object obj){
System.out.println(obj);
}
}
【2】
【2-1】UDP 特点
1、将数据及源和目的防装成数据包中,不需要建立连接
2、每个数据包的大小都限制在64K内
3、不需要建立连接,速度快
4,因不需要连接,是不可靠协议。
(1、无连接  2、不可靠  3、<= 64K包 4、速度快)
聊天、视频会议、桌面共享等都可以用UDP传输

【2-2】UDP 传输
1、DatagarmSocket   和     DatagramPacket 
2、建立发送端,接收端
3、建立数据包
4、调用Socket发送数据,接收数据方法。
send()发送
receive() 接收

5、关闭 Socket
---
【2-3】发送端:
1、建立 udpsocket服务(DatagramSocket 发送端)
2、建立 并 封装数据, (DatagramPacket(数组,发送其长度,接收地址,接收端口))
3、通过 socket 服务的发送功能,将数据包发送
4、关闭资源
class Send 
{
public static void main(String[] args) throws Exception
{
//哈哈,实现了,一对一聊天。
//创建udp 服务
DatagramSocket ds = new DatagramSocket();

BufferedReader bufr = //接收键盘录入
new BufferedReader(new InputStreamReader(System.in));

String line = null;
//封装数据
while((line = bufr.readLine())!=null){
if("886".equals(line))
break;
byte [] buf = line.getBytes();

DatagramPacket dp = //指定数据包,数据包大小(长度),主机,端口
new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10000);
ds.send(dp); //很关键的一步,发送动作
}
ds.close();
}
}
【2-4】接收端:
1、定义 udpsocket 服务、通常会监听一个端口,其实就是接收网络应用程序自定义数字表示(端口号)
方便与明确那写数据过来,该应用程序可以处理。
2、定义一个数据包,因为要储存接收到的字节数据
因为数据包对象中有很多功能可以提取字节数据,存入以定义好的数据包中。
3、通过 socket 服务的 receive 方法将接收到的数据存入已经定好的数据包中
4、通过数据包对象特有的功能,将这些不同是数据取出,打印在控制台上。
5,关闭资源
class Receive
{
public static void main(String[] args) throws Exception
{
// 创建 udp socket 建立断点,【并指定端口号】
DatagramSocket ds = new DatagramSocket(10000);//

while(true){ //循环接收 对方发送的数据
byte [] buf = new byte[1024];//建立一个数组,用于接收拆包后数据

DatagramPacket dp = new DatagramPacket(buf,buf.length);//通过该类特有方法,进行拆包。

ds.receive(dp);//接收数据并给 DatagramPacket 进行拆包

String ip = dp.getAddress().getHostAddress();//获取对方ip

String data = new String(dp.getData(),0,dp.getLength());//获取数据信息。 getLength()实际长度

int port = dp.getPort();//对方端口

sop(ip);
sop(data);
sop(port);
}
//ds.close();
}
public static void sop(Object obj){
System.out.println(obj);
}
}
UDP  不需要连接、如果对方没有开启接收端,数据丢失。
【3】
【3-1】TCP 特点:
1、必须建立连接
2、大数据传输
3、通过三次握手完成连接,可靠连接
4、必须建立连接 ---效率稍低
下载使用的就是 TCP协议

【3-2
     Socktet】 --   就是通常所说的网络编程
1、Socket  就是为网络服务提供的一种机制
2、通信的两端都有Socket
3、网络通信其实就是Socket 间的通信
4、数据在两个Socket 之间通过IO传输
【3-3】TCP 传输
1、Socket    和    ServerSocket
2、建立客户端和服务端
3、建立客户端后通过 Socket 中的 IO流 进行数据的传输
4、关闭


【3-4】
演示  【 TCP 】 传输
1、tcp 分 客户端、服务端
2、 客户端对应的是 Socket
服务端对应的是 ServerSocket


客户端
------
通过查阅 socket 对象,发现给对象建立时,就可以去连接指定主机。
因为TCP 是面向连接的,所以在建立 socket 服务时
就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输。


步奏:
1、创建socket 服务,并指定要连接的主机和端口  Socket();
2、为 发送数据,应该获取 socket 流(网络流) 中的输出流。 getOutputStream();
3、//使用网络输出流 进行数据的书写
--------------------------------
class TcpClient
{

public static void main(String[] args) throws Exception
{
//Date d=null;
Socket s = new Socket("127.0.0.1",10005);

OutputStream out = s.getOutputStream();

out.write("美女,你在干嘛~".getBytes());
//d =new Date();
String de = time(new Date());
System.out.println("\t\t"+de);
System.out.println("\t\t\t\t美女,你在干嘛~");
//2

InputStream in = s.getInputStream();
byte [] buf = new byte[1024];
int len = in.read(buf);
//3
de = time(new Date());
System.out.println("\t\t"+de);
System.out.println("美女:"+new String(buf,0,len));
s.close();
}
public static String time(Date d){

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String de = sdf.format(d);
return de;
}
}
服务端
------
1、建立服务端的 socket 服务。 ServerSocket(); 并监听一个端口(指定)
2、获取连接过来的客户端对象。通过 accept(); 方法 没有连接就会等
所以,accept同  receive 同 System.in 同 Reader    都是阻塞式
3、客户端如果发过来数据,那么服务端要使用对应的客户端对象,
并获取到该客户端对象的读取流来读取发过来的数据。
4、关闭 服务端  (可选)
--------------------------
class TcpServer
{

public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10005);
Socket s = ss.accept();

String ip = s.getInetAddress().getHostAddress();
//3
String de = time(new Date());
System.out.println("\t\t"+de);
//System.out.println("信息来自:"+ip);

InputStream in = s.getInputStream();
byte [] buf = new byte[1024];
int len = in.read(buf);

System.out.println("帅哥:"+new String(buf,0,len));

//2

OutputStream out = s.getOutputStream();
Thread.sleep(6000);//延缓几秒发送,模拟聊天嘛。
out.write("想你啊!~".getBytes());

Date d =new Date();
de = time(d);
System.out.println("\t\t"+de);
System.out.println("\t\t\t\t想你啊!~");
s.close();
ss.close();
}
public static String time(Date d){

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String de = sdf.format(d);
return de;
}
}
服务端同 客户端很类似
一个是先发送数据,一个是接收后在发送数据


【3-4】
需求:
设定一个  服务端-- 客户端    实现多客户同时上传功能。指点为 jpg 图片
-----------
客户端:
1、建立 客户端 服务 并指定主机 和端口 socket
2、读取  读取图片的流 ,和写入网络的输出流, BufferedInputStrean--  OutputStream--getOutputStream();
3、定义数组,,动过循环读取图片数据,并写入网络输出流中
4、定义读取数据,接收 网络读取流,获取服务器的反馈信息 InputSteram  getInputStream
5、注意表示 输出流结束标记      最后关闭资源
6、发现: 指定文件不能达到多客户上传, 进行 主函数 接收一个文件地址进行 模拟多客户 上传
7、对 接收到的文件进行 判断 1、是否存在 2、是否为jpg 格式 3、是否 超大提及、
满足条件后才执行  建立客户端服务
-----------
服务端
1、建立 服务端  并指定端口 ServerSocket
1-1 获取客服端 --连接对象accept
2、建立 读取流,,读取 获得网络流中的数据 BuferedReader    getInnputStream
3、读取完毕后,给予反馈信息  OutputStream 或者PrintWriter     getOutputStream
4、关闭。
5、发现: 即使   添加一个whlie(true)   也只能一个用户进行上传>>   多线程
线程应该初始化 就接收 一个客户端连接对象   而公共代码方法 run 方法中
6、通过在服务端 主线程中, 进行whlie(true)   添加一个匿名
new thread(new xianc(s)).start();

当 在主线程中添加上面 线程后, 主线程先执行,传入一个 A 客户端连接对象、,
建立一个A 线程,进行上传,这个时候 程序有两个线程,当执行主线程的时候,
循环 true 又进来一个 B 客户端连接对象,又创建B线程 一直循环
从而达到多线程完成上传。
//客户端
class Client
{
public static void main(String[] args) throws Exception
{//9、 对传入的 参数进行判断 只能传 一个
if(args.length != 1 ){
sop("输入一个图片以及其地址");
return;
}
//8、接收一个主函数参数 并封装为一个 对象
File file = new File(args [0]);
//10、对不合格各---种格式--进行--逐一判断。
if(!file.exists() && file.isFile()){
sop("路径或文件不正确");
return;
}
if(!file.getName().endsWith(".jpg")){
sop("格式不正确");
return;
}
if(file.length()>1024*1024*5){
sop(" 图片体积过大");
return;
}
//11、 符合上面条件后,程序进行下一步 进行连接主机:

//1、建立 socket 服务,并绑定 主机ip 和端口
Socket s = new Socket("127.0.0.1",10002);
//2、建立 读取流 读取 本地文件
BufferedInputStream bufi = new BufferedInputStream(new FileInputStream(file));
//3、建立 输入流 接收 网络输入流
OutputStream out = s.getOutputStream();
//4、 建立一个数组, 循环遍历将数据装入数组
byte [] by = new byte[1024];
int len = 0;
while((len = bufi.read(by)) != -1){
//4-1 遍历满一组数组,就将数据写入到 网络输入流中 并进行刷新发送
out.write(by,0,len);
out.flush();

}
//5、【很关键的一步】: 指定 结束标记 相当于-1
s.shutdownOutput();
//6、接收 服务端反馈的信息 定义一个读取流 接收 网络读取流
BufferedReader in = new BufferedReader( new InputStreamReader(s.getInputStream()));

String str = in.readLine();
sop(str);
//7、 关闭相关资源
s.close();
bufi.close();

}
public static void checkFile(){

}
public static void sop(Object obj){
System.out.println(obj);
}
}


// 服务端
class Server
{
public static void main(String[] args) throws Exception
{
//1、构建 服务端 并绑定端口
ServerSocket ss = new ServerSocket(10002);

//4 循环-当有多个客户端同时上传时,会--先后-获取到不同的 客户端连接对象 从而
//创建出不同的线程,达到多客户同时上传的效果。
while(true){
//2、 获取的客户端 连接对象
Socket s = ss.accept();
//3、根据客户端连接对象 创建一个新的线程
new Thread(new picThread(s)).start();
}

}
}

// 处理上传---线程
class picThread implements Runnable
{
private Socket s;
//1、把 客户端--连接对象 传入 线程 进行初始化。
picThread(Socket s ){
this.s = s ;
}
public void run(){
int count=1;
File file;
//0、run方法中必须try
try
{
//8、 通过根据不同客户端的不同ip 进行文件的存储,
String ip = s.getInetAddress().getHostAddress();
//8-1 当没有这个文件的时候:
file = new File("D:\\TCP\\"+ip+".jpg");
//8-2 循环:当有了这个文件后,利用计数器 递增文件名
while(file.exists()){
file = new File("D:\\TCP\\"+ip+"("+(count++)+").jpg");
}
//2、创建 并接收 网络 读取流
InputStream in = s.getInputStream();
//3、 创建一个输出流,并绑定一个写入的目的
BufferedOutputStream bufw = new BufferedOutputStream(new FileOutputStream(file));
//4、定义数组,循环读取网络流中数据,存入数组
byte [] by = new byte[1024];
int len = 0 ;
while((len = in.read(by)) != -1){
//4-1 每满一个数组 就写入到目的中
bufw.write(by,0,len);
bufw.flush();
}
//5 服务端 对客户端进行反馈信息 两种表现方式:
//写入方式1
OutputStream out = s.getOutputStream();
out.write("上传成功!~".getBytes());

//写入方式2
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.println("丫!~妈的!~");
//6、关闭相关资源
s.close();
bufw.close();
}
catch (Exception e)
{
//7、抛出 RuntimeException
throw new RuntimeException("上传失败");
}

}
}
【4-5】
练习
需求:
客户端通过键盘录入用户名
服务端对这个用户名进行校验


如果用户存在,在服务端显示XXX 已登录
并在客户端显示XXX 欢迎回来


如果该用户不存在,在服务端显示XXX 尝试登录
并在客户端显示 XX该用户不存在


--------------
分析:


1、服务端:键值对存贮信息。
2、 客服端 :录入 用户名,  
1、流--读取键盘
2、读取流传入--网络输出流--发送
3、服务端
1、定义流 接收-网络流, 
2、获取 用户名  
3、建立读取流 读取 键值对文件 用户名
4、两个用户名,进行匹配。
5、成功返回 欢迎,等情况
class Client 
{
public static void main(String[] args) throws Exception
{// 建立--客户端--绑定ip、端口
Socket s = new Socket("127.0.0.1",10004);
// 建立--读取流--接收--键盘录入
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//建立--输出流--绑定 网络输出流--记住一定要true-否则不刷新
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
// 建立--读取流--绑定--网络读取流
BufferedReader in =
new BufferedReader(new InputStreamReader(s.getInputStream()));
//限制--最多3 次登录 机会
for(int i = 0; i<3 ; i++){
// 获取--键盘录入信息--只有一行的--空或者ctrl+c 跳出循环
String line =bufr.readLine();
if(line==null)
break;
// 网络输出流 --发送数据
pw.println(line);
// 网络读取流--获取--服务端反馈信-- 如果包含成功登陆关键字,结束循环
String info = in.readLine();
System.out.println("::"+info);
if(info.contains("欢迎"))
break;
}
// 关闭相关资源
s.close();
bufr.close();
}
}
【5】
URL--URLConnection
openConnetion() 返回主机连接对象   -- 应用层  
该对象方法主动连接,就不用写Socket对象了。 -- 传输层






---------------------------------------------------------------------------------------------------------------------------------------------
---------- android培训、 java培训、期待与您交流!---------- 黑马官网

----------------------------------------------