网络编程是基于网络进行数据传输I(IO流)。
参考模型
一、UDP协议:
底层基于流,传输不建立连接,不安全(不可靠)但是速度快
适用场景:直播、视频、音频等等
底层根据数据包(64KB)来进行数据传输
1.1发送端
1.创建UDP发送端对象
2.创建数据包(指定IP地址、端口号以及要发送数据)
3.发送数据包
4.关流
public static void main(String[] args) throws IOException {
//创建UDP发送端的对象
DatagramSocket ds=new DatagramSocket();
//创建数据包对象---准备发送数据
//第一个参数--代表发送的数据
//第二个参数---代表实际发送内容长度
//的三个参数---代表IP地址和端口号
DatagramPacket dp=new DatagramPacket("早上好".getBytes(),"早上好".getBytes().length,new InetSocketAddress("127.0.0.1",8081));
//发送数据包
ds.send(dp);
//关流
ds.close();
}
1.2接收端
1.创建UDP接收端对象,监听端口号
2.创建数据包(接收发送端发送数据)
3.接收数据包
4.关流
5.解析数据包
public static void main(String[] args) throws IOException {
//创建UDP接收端对象---监听发送端的端口号
DatagramSocket ds=new DatagramSocket(8081);
//创建数据包对象---接收数据
//第一个参数--代表来接收数据的字节数组
//第二个参数--代表真实的接收数据内容的长度
DatagramPacket dp=new DatagramPacket(new byte[1024],1024);
//接收发送端发送数据
ds.receive(dp);//会让线程阻塞状态
//关流
ds.close();
//解析数据包
//返回IP地址
System.out.println(dp.getAddress());
//getData--接收到的数据
//getLength--接收的数据内容的长度
//展示接收的数据
System.out.println(new String(dp.getData(),0,dp.getLength()));
}
二、 TCP协议
底层基于流,传输建立连接(三次握手),安全(可靠),传输速度慢
适用场景:上传和下载、聊天等等
底层根据IO流来进行数据传输,不限制传输数据大小
socket中发送的TCP三次握手
从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN
J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK
J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN
K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。
socket中发送的TCP四次握手(四次挥手)
图示过程如下: 某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M; 另一端接收到FIN
M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
接收到这个FIN的源发送端TCP对它进行确认。 这样每个方向上都有一个FIN和ACK。
2.1客户端:
1.创建TCP客户端对象
2.发起连接(指定IP地址和端口号)
3.获取自带字节输出流往服务器端写出数据
4.写出数据
5.通知服务器端数据已经发送完毕
6.关流
public static void main(String[] args) throws IOException {
//创建 TCP的客户端对象
Socket s=new Socket();
//发起连接
s.connect(new InetSocketAddress("127.0.0.1",9092));//让线程对象阻塞
//获取自带的字节输出流
//默认往服务器端来传输
OutputStream os=s.getOutputStream();
//写出数据
os.write("下午好".getBytes());
//通知服务器端数据已经发送完毕
s.shutdownOutput();
//从服务器端来读取数据
//获取自带字节输入流
InputStream is=s.getInputStream();
//自建缓冲区--自建数组
byte[] bs=new byte[1024];
int len=-1;
while ((len=is.read(bs))!=-1){
//展示读取到数据
System.out.println(new String(bs,0,len));
}
//通知服务器端数据已经读取完毕
s.shutdownInput();
//关流
s.close();
}
2.2 服务器端:
1.创建TCP服务器端对象,监听端口号
2.接收连接
3.获取自带字节输入流从客户端来读取数据
4.读取数据
5.通知客户端数据已经读取完毕
6.关流
public static void main(String[] args) throws IOException {
//创建TCP服务器端对象---监听端口号
ServerSocket ss=new ServerSocket(9092);
//接收连接
Socket s=ss.accept();//让线程对象进行阻塞
//获取自带的字节输入流(默认读取客户端发送数据)
InputStream is=s.getInputStream();
//自带缓冲区--自建数据
byte[] bs=new byte[1024];
int len=-1;
//让线程对象阻塞
while ((len=is.read(bs))!=-1){
//把数据读取到服务器
System.out.println(new String(bs,0,len));
}
//通知客户端数据读取完毕
s.shutdownInput();
//把服务器端的数据发送到客户端
//获取自带字节输出流---往客户端发送数据
OutputStream os=s.getOutputStream();
//发送数据
os.write("你也好".getBytes());
//通知客户端数据已经发送完毕
s.shutdownOutput();
//关流
s.close();
ss.close();
}