Java网络编程相关知识

本文介绍了Java网络编程的基础知识,包括IP、端口号和协议的概念,详细讲解了UDP和TCP协议的特点,以及UDP的三种通信方式。同时阐述了TCP的三次握手和四次挥手协议,以及在Java中使用Socket进行TCP通信的流程。最后提到了UUID在文件命名中的应用。

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

网络编程

1.在网络通信协议下,不同 计算机上运行的程序,进行的数据传输。

2.应用场景:即时通信、网游对战、金融证券、国际贸易、邮件等等。

3.Java中可以使用java.net包下的技术开发出常见的网络应用程序。

4.常见的软件架构有CS和BS两种:

  • CS(Client/Server,客户端/服务器)

用户需要在本地下载并安装客户端程序,在远程有一个服务器端程序。

优点:画面可以做的非常精美,用户体验好

缺点:

1)需要开发客户端,也需要开发服务端

2)用户需要下载和更新比较麻烦

适合定制专业化的办公类软件,比如:IDEA、网游

  • BS(Browser/Server,浏览器/服务器)

只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器。

优点:

1)不需要开发客户端,只需要页面 + 服务端

2)用户不需要下载,打开浏览器就能使用

缺点:如果应用过大,用户体验会受到影响(因为实时传输数据,画质等会受影响)

适合移动互联网应用,可以在任何地方随时访问的系统

5.网络编程三要素:

  • 确定电脑在互联网上的地址:IP,IP是设备在网络中的地址,是唯一的标识
  • 确定接收数据的软件:端口号,端口号是应用程序在设备中唯一的标识
  • 确定网络传输的规则:协议,协议是数据在网络中传输的规则,常见的协议有UPP、TCP、http、https、ftp

IP

1.IP全程Internet Protocol,是互联网协议地址,也称IP地址。是分配给上网设备的数字标签。通俗理解就是上网设备在网络中的地址,是唯一的。

2.常见的IP分类为:

  • IPv4:全称:Internet Protocol version 4,互联网通信协议第四版

1)采用32位地址长度(4字节),分为4组,每组长度为0-255,总共数量为2^32,但是仍然存在不够用的问题

2)采用点分十进制表示法,比如192.168.1.16

IPv4的地址分类形式:

1)公网地址(万维网使用)和私有地址(局域网使用)。

2)192.168.开头的就是私有地址,范围即为192.168.0.0 - 192.168.255.255,专门为组织机构内部使用,以此节省IP

特殊IP地址:

127.0.0.1,也可以是localhost:是会送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在本机。

因为发送数据时,会先往路由器发送,然后路由器根据给出的IP地址再传到对应的IP地址处,即使是发送到的IP地址是本机的IP地址,而使用127.0.0.1去发送,就可以不经过路由器,在发送时网卡识别了,直接就传到本机

  • IPv6:全称:Internet Protocol version 6,互联网通信协议第六版

1)为了解决IPv4不够用而出现的,提供了更多的IP地址,采用了128位地址长度,分成8组,每组的长度为0-2^16 - 1,总共数量为2^128。

2)采用冒分十六进制表示法,比如2001:0DB8:0000:0023:0008:0800:200C:417A,还可以省略每组的前面的0:2001:DB8:0:23:8:800:200C:417A

3)特殊情况:如果计算出的16进制表示形式中间有多个连续的0,可以使用0为压缩表示法,就是将连续的0省略不写,比如:FF01:0:0:0:0:0:0:1101 -> FF01::1101

3.常见的与IP相关的CMD命令:

  • ipconfig:查看本机IP地址
  • ping IP地址/网址(其实是网址对应的服务器IP):检查当前主机与对应IP的设备网络是否连通

4.与IP相关的类InetAddress:

  • 有两个子类Inet4Address和Inet6Address,InetAddress会根据本机使用的是IPv4还是使用IPv6去创建对应的对象
  • 只能通过InetAddress的静态方法getByName(String host)去创建InetAddress对象,不能直接new,String host可以传本机的IP地址或者主机名。主机名可打开此电脑,右键属性去查看计算机名
  • 创建的InetAddress是IP的对象,可以直接看作是一台电脑的对象
  • 相关方法
方法名说明
String getHostName()获取主机名
String getHostAddress()获取主机对应的IP地址

端口号

1.应用程序再设备中唯一的标识,因此一个端口号只能被一个应用程序使用。

2.由两个字节表示的整数,取值范围:0~65535。其中0~1023之间的端口号用于一些知名的网络服务或者应用,一般自己使用的是1024以上的端口号。

协议

1.计算机网络中,连接和通信的规则被称为网络通信协议。

2.OSI参考模型:世界互联协议标准,全球通信规范,但模型过于理想化,未能再因特网上进行广泛推广。

3.TCP/IP参考模型(或TCP/IP协议):对OSI中应用层表示层会话层进行了合并,数据链路层和物理层进行了合并,事实上的国际标准。

 4.UDP协议:

  • 用户数据报协议(User Datagram Protocol)
  • UDP是无连接、不可靠的通信协议,速度快,有大小限制,以此最多发送64K,数据不安全,易丢失数据
  • 无连接就是不检查设备之间是否连通就直接发送,只管发送,不管能不能收到
  • 适用场景:网络会议、语音通话、在线视频(能接受丢失部分数据的场景)

5.TCP协议:

  • 传输控制协议TCP(Transmission Cotrol Protocol)
  • TCP协议是面向连接的通信协议,速度慢,没有大小限制,数据安全
  • 适用场景:下载软件、文字聊天、发送邮件(不能丢失一点数据的场景)

UDP协议发送数据

以寄快递为例,步骤为四步:

1.找快递公司 ----- 创建发送端的DataGramSocket对象

2.打包礼物 ----- 数据打包(DatagramPacket)

3.快递公司发送包裹 ----- 发送数据

4.付钱走人 ----- 释放资源

// 1.找快递公司(创建发送端的DataGramSocket对象)
// 细节:
// 绑定端口,通过这个端口往外发送
// 空参:所有可用的端口中随机一个进行使用
// 有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket();
        
// 2.打包数据
String str = "check check check";
// 因为在数据打包的时候,创建的DatagramPacket对象需要传入的是
// 字节数组,起始索引(可省略),传入数据长度,IP,端口号,因此先把这几个给先准备好
byte[] datas = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10000;
DatagramPacket dp = new DatagramPacket(datas,datas.length,address,port);
        
// 3.发送数据
ds.send(dp);
        
// 4.释放资源
ds.close();

UDP协议接收数据

以接收快递为例

1.找快递公司 ----- 创建接收端的DatagramSocket对象

2.接收箱子 ----- 接收打包好的数据

3.从箱子里面获取礼物 ----- 解析数据包

4.签收走人 ----- 释放资源

需要注意的是这里需要先启动接收数据程序,再启动发送数据程序,因为UDP发送数据是只负责发送,不查看是否连通设备,而先启动接收数据程序可以保证先连通,receive方法在接收到数据前会一直等待。

// 1.创建DatagramSocket对象(快递公司)
// 细节:
// 在接受的时候,一定要绑定端口
// 而且绑定的端口是跟发送时绑定的端口一致
DatagramSocket ds = new DatagramSocket(10000);

// 2.接收数据包
// 因为数据传输过来时的数据使用byte数组传输过来,接收时也是用byte数组接收
// byte数组的长度一定要大于传输过来数组长度,否则丢失数据
byte[] bytes = new byte[1024];
// 因为这里是接收数据,因此只需要把接受的长度以及接收的数组传过去即可
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);

// 3.解析数据包
byte[] data = dp.getData(); // 获取数据包中的有数据部分
int len = dp.getLength(); // 获取数据包中的数据部分长度
InetAddress address = dp.getAddress(); // 获取发送的设备的IP地址
int port = dp.getPort(); // 获取发送的设备发送时使用的端口号
System.out.println("接收到数据" + new String(data,0,len));
System.out.println("该数据是从" + address + "这台电脑中的" + port + "端口发出的");

// 4.释放资源
ds.close();

UDP的三种通信方式

三种方式的区别就是在(找快递公司时)创建对象时的对象不同。

1.单播,一对一通讯。创建的是DatagramSocket对象。

2.组播,一对一组通讯。组播地址:224.0.0.0~239.255.255.255,其中224.0.0.0~224.0.0.255为预留的组播地址,一般只用这个范围内的组播地址。如果对组播地址中的任意一个地址发送信息,则在局域网中的处于组播地址中的所有电脑都能接收到该信息。创建的是MulticastSocket对象,如果想要当前主机也在组播地址内,可以先创建一个以224.0.0.1为形参的InetAddress对象address,再使用ms(ms为MuticastSocket实现类)的方法,ms.joinGroup(address)即可将本机添加到组播地址。

3.广播,一对所有通讯。广播地址:255.255.255.255,如果对广播地址发送信息,则在局域网中的所有电脑都会收到该信息

TCP通信程序

1.TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,通信之前要保证连接已经建立,通过Socket产生IO流来进行网络通信。

2.通信过程(客户端Socket发送数据):

  • 创建客户端的Socket对象(Socket)与指定服务端连接 Socket(String host,int port)
  • 获取输出流,写数据 OutputStream getOutputStream()
  • 释放资源 void close()
// 1.创建客户端的Socket对象,参数中是连接的服务器的IP和对应端口
Socket socket = new Socket("127.0.0.1",10000);
// 2.获取输出流,写数据
OutputStream os = socket.getOutputStream();
Scanner sc = new Scanner(System.in);
String str;
while(true){
    str = sc.nextLine();
    os.write(str.getBytes());
    if("886".equals(str)){
        break;
    }
}
// 3.释放资源
socket.close();

3.通信过程(服务器端ServerSocket接收数据):

  • 创建服务器端的Socket对象(ServerSocket) ServerSocket(int port) ,这个port一定要去客户端的发送到的指定端口相同
  • 监听客户端连接,返回一个Socket对象 Socket accept()
  • 获取输入流,读数据,并把数据显示在控制台 InputStream getInputStream(),如果发送的是中文的数据,需要使用转换流将字节流转换为字符流再去读数据,否则容易乱码,如果想要使用缓冲流中的读取一行的方法,也可以进一步提升为缓冲流
  • 释放资源 void close();释放资源时只要把通道关闭,输入流就自动关上了,因为输入流是通过Socket的实现类对象获取的,因此释放掉Socket资源就会同时释放输入流,客服端的输出流也是同理
// 1.创建服务器端的Socket对象
ServerSocket ss = new ServerSocket(10000);
// 2.监听客户端连接,返回一个Socket对象
Socket socket = ss.accept();
// 3.获取输入流,读取数据
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
int b;
while ((b = isr.read()) != -1) {
    System.out.print((char) b);
}
// 4.释放资源
socket.close();
ss.close();

4.在运行代码时要先运行服务端,因为先运行客户端时会发现没有服务端与其相连,就会报错,先运行服务端就会等待连接,不会报错。

5.在服务器端使用输入流读取数据时,判断流是否已经读完能否看读到最后会返回-1?

答:返回-1取决于处理的流的源头是什么,如果是文件流,这种想法或许是对的,因为文件流的大小是固定的,持续的读,总会读到文件的末尾(EOF),它总会返回-1的。但是,如果是网络流,例如TcpSocket,这样的流是没有末尾(EOF)的,如果你想读到-1,或许在远端被关闭了,而你还在读取,还是有可能读到-1的。实际情况是:网络连接状况很复杂,很有可能远端没有正常关闭而是进程死掉了,而是连接的线路断掉了,或者任何一个原因导致连接的通路无法正常传输数据。因此,如果连接没有断开,或者没有其他的原因导致传输异常,输入流会一直等输出流的数据,当使用Socket.shutdownOutpu()t或者异常情况出现的时候,使用输入流的read就会读取到-1。shutdownOutput方法相当于一个结束标记。

这里采用另一位博主的回答,我把相关的内容概括了一下。

https://blog.youkuaiyun.com/myling0626/article/details/50413268

TCP中的三次握手和四次挥手协议

1.三次握手:确保连接建立。服务端收到请求后不会马上建立连接,而是等客户端再次发出确认信息才会建立连接。

2.四次挥手协议:确保连接断开,保证连接通道里面的数据已经处理完毕了。

UUID

1.当上传文件时,文件名一般不能写定,最好使用一个每次都不一样的变量去命名,这个时候就可以使用UUID里面的randomUUID方法。

2.randomUUID方法是静态的,返回一个UUID类对象,使用其toString方法获取对应字符串,最后将格式转换一下即可。(不转换格式的输出类似c7322330-a405-4caa-9e2d-233b4fd3b3cb)

String name = UUID.randomUUID().toString.replaceAll("-");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值