网络编程:
1.什么是网络编程?
网络编程是可以让设备中的程序与网络上其他设备中的程序进行数据交互的技术
2.网络通信三要素
1.IP地址
IP(Internet Protocol):全称”互联网协议地址”,是分配给上网设备的唯一标识,可以用来定位网络上的设备。
IP地址有两种形式:
IPv4: 32位,4个字节点分十进制: 192.168.1.66
IPv6:128 冒分十六进制: 2001:0db8:0000:0023:0008:0800:200c:417a
IP域名: 网址
公网IP, 内网IP:
公网IP:是可以连接互联网的IP地址;内网IP:也叫局域网IP,只能组织机构内部使用。
内网IP:192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用。
特殊IP地址:127.0.0.1、localhost:代表本机IP,只会寻找当前所在的主机。
IP常用命令:
ipconfig :查看本机IP地址
ping IP地址:检查网络是否连通
Java中IP地址的表示:
InetAddress
2.端口号
标记正在计算机设备上运行的应用程序的,被规定为一个 16 位的二进制,范围是 0~65535
分类:
周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用 80,FTP占用21)
注册端口:1024~49151,分配给用户进程或某些应用程序
动态端口:49152到65535,之所以称为动态端口,是因为它 一般不固定分配某种进程,而是动态分配
注意:我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。
3.协议
1.网络上通信的设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议
2.开放式网络互联标准
OSI网络参考模型:全球网络互联标准
TCP/IP网络模型:事实上的国际标准
3.传输层的2个通信协议
UDP:用户数据报协议
特点:
无连接、不可靠通信,通信效率高
不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口,目的地IP、程序端口和数据(限制在64KB内)等。
发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故是不可靠的 。
应用场景:语音通话、视频直播
TCP:传输控制协议
特点:
面向连接、可靠通信
要保证在不可靠的信道上实现可靠的传输
TCP主要有三个步骤实现可靠传输:
三次握手建立可靠连接:目的确定通信双方,收发消息都是正常无问题的!(全双工)
传输数据进行确认:目的保证传输数据的可靠性
四次挥手断开连接:目的确保双方数据的收发都已经完成!
应用场景:网页、文件下载、支付
下面来主要介绍UDP和TCP在java中的代码实现
1.UDP:
案例:一个类似聊天室的项目
先上代码:
package comitawei;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class SendMessageDemo {
//main 方法声明 throws IOException 是因为代码中涉及网络操作,这些操作可能会因为网络问题或资源不可用而失败,需要通过 IOException 来处理异常情况。
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("请输入要发送的内容:");
String str = sc.nextLine();
if ("886".equals(str)){
break;
}
byte[] bytes = str.getBytes();
InetAddress addess = InetAddress.getByName("127.0.0.1");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, addess, port);
ds.send(dp);
}
ds.close();
}
}
------------------------------------------------------------------------------------------
package comitawei;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiveMessageDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10086);
DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
while(true) {
ds.receive(dp);
byte[] data = dp.getData();
int len = dp.getLength();
String ip = dp.getAddress().getHostAddress();
String name = dp.getAddress().getHostName();
System.out.println("ip为:" + ip + "主机名为:" + name + "的人,发送了数据:" + new String(data, 0, len));
}
}
}
具体步骤:
客户端实现步骤:
创建DatagramSocket对象(客户端对象)
创建DatagramPacket对象封装需要发送的数据(数据包对象)
使用DatagramSocket对象的send方法,传入DatagramPacket对象
释放资源
服务端实现步骤
创建DatagramSocket对象并指定端口(服务端对象)
创建DatagramPacket对象接收数据(数据包对象)
使用DatagramSocket对象的receive方法,传入DatagramPacket对象
释放资源
我这里用while循环实现了多发多送
2.TCP:
代码:
package cmditweige;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
//TCP协议
public class Client {
public static void main(String[] args) throws IOException {
//如果连接不上,会报错
Socket socket =new Socket("127.0.0.1",10000);
OutputStream os=socket.getOutputStream();
//写出数据
os.write("你好 你好".getBytes());
//释放资源
os.close();
socket.close();
}
}
---------------------------------------------------------------------------------
package cmditweige;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(10000);
//监听客户端的链接
Socket socket=ss.accept();
//从连接通道中获取输入流读取数据
InputStream is =socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br =new BufferedReader(isr);
int b;
while((b=br.read())!=-1) {
System.out.print((char)b);
}
socket.close();
ss.close();
}
}
2.客户端实现步骤
创建客户端的Socket对象,请求与服务端的连接。
使用socket对象调用getOutputStream()方法得到字节输出流。
使用字节输出流完成数据的发送。
释放资源:关闭socket管道。
3.服务端实现步骤
创建ServerSocket对象,注册服务端端口。
调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。
通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收。
释放资源:关闭socket管道
关键步骤详解
1. 客户端发起连接(TCP三次握手)
- 步骤:
- 客户端发送
SYN
报文(携带初始序列号)。 - 服务器回复
SYN-ACK
报文(确认收到并发送自己的序列号)。 - 客户端发送
ACK
报文,完成握手。
- 客户端发送
2. 数据传输
- 发送端:
- 应用层数据 → 传输层(TCP分段) → 网络层(IP包) → 数据链路层(帧) → 物理层(电信号)。
- 接收端:
- 物理层 → 数据链路层 → 网络层 → 传输层(重组数据) → 应用层。
3. 服务器端处理
- **
bind()
**:绑定本地IP和端口。 - **
listen()
**:进入监听状态,维护半连接队列和全连接队列。 - **
accept()
**:从队列中取出合法连接,创建新Socket处理数据。
4. 关闭连接(TCP四次挥手)
- 步骤:
- 客户端发送
FIN
报文。 - 服务器回复
ACK
。 - 服务器发送
FIN
。 - 客户端回复
ACK
,连接关闭。
- 客户端发送