建设vip电影网站,营销型网站建设哪好,wordpress 小工具 文本,附近建网站公司写在前
简单描述一下关于路由器的三层转发和交换机的二层转发。
路由器是三层转发--在网络层转发。【需要解析出IP协议中的源IP、目的IP来规划路径】
交换机是二层转发--在数据链路层转发。【只需要关注下一步发展到哪个相邻的设备上#xff0c;不需要IP地址#…写在前
简单描述一下关于路由器的三层转发和交换机的二层转发。
路由器是三层转发--在网络层转发。【需要解析出IP协议中的源IP、目的IP来规划路径】
交换机是二层转发--在数据链路层转发。【只需要关注下一步发展到哪个相邻的设备上不需要IP地址在数据链路层。有一个mac地址。】
这一部分开始进行网络部分的内容涉及到编程相关的知识好好学习
本篇博客主要是对网络编程进行初步的了解socket的理解学习相关API、完成客户端、服务器的【回显服务器】代码编写在同一台主机上完成通信。
目录
写在前
1.网络编程基础
1.1什么是网络编程
1.2常见的客户端服务端模型
2.Socket套接字
2.1概念
2.2分类
2.2.1流套接字-TCP
2.2.2数据报套接字-UDP
2.3Java数据报套接字通信模型
2.4UDP数据报套接字编程
2.4.1DatagramSocket API
2.4.2DatagramPacket API
2.4.3InetSocketAddress API
2.4.4服务器代码实现
核心思想
代码实现
加注释版本
需要强调的内容
2.4.5客户端代码实现
核心思想
代码实现
加注释版本
理解服务器与客户端端口
2.4.6服务器和客户端执行顺序
2.4.7IDEA多个客户端设置操作
2.4.8客户端服务器执行结果 1.网络编程基础
1.1什么是网络编程
网络编程指网络上的主机通过不同的进程【只要满足不同的进程就行所以即便是同一个主机只要是进程不同基于网络来传输数据也属于网络编程。】以编程的方式实现网络通信或称为网络数据传输。
1.2常见的客户端服务端模型
最常见的场景客户端是指给用户使用的程序服务端是指提供用户服务的程序。
1客户端先发送请求到服务端。
2服务端根据请求数据执行相应的业务处理。
3服务端返回响应发送业务处理结果。
4客户端根据响应数据展示处理结果战术获取的资源或提示保存资源的处理结果
2.Socket套接字
2.1概念
Socket套接字是由系统提供用于网络通信的技术是基于TCP/IP协议的网络通信的基本单元。基于Socket套接字的网络程序开发就是网络编程。
【socket 英文原意为插座。socket是操作系统给应用程序提供的网络编程的API可以认为socket API是和传输层密切相关的传输层里提供了两个核心的协议TCP和UDP。所以socket api提供了两种风格TCP和UDP 准确的讲有三种unix域套接字几乎没人用】
2.2分类
一些解释
可靠传输网络环境是天然复杂的。不可能保证传输的百分百到达可靠传输指的是发送方能知道自己的消息发过去了。
是否是可靠传输与是否有无连接没有关系例如在一些聊天软件上的“已读”功能是无连接的可靠传输。
全双工半双工一个通信通道可双向传输既可以发送也可以接收就是全双工一根水管只能单项传输叫做半双工。TCP/UDP都是全双工是因为一根网线中有八根线
2.2.1流套接字-TCP
TCP,Transmission Control Protocol传输控制协议传输层协议。
特点有连接可靠传输面对字节流有接收缓冲区也有发送缓冲区大小不限全双工。
类似于打电话打电话就是有连接的需要连接建立才能通信。连接建立需要对方“接受”如果连接没建立好则不能进行通信。
对于字节流来说可以简单地理解为传输数据是基于IO流的流式数据的特征就是在IO流没有关闭的情况下是无边界的数据可以多次发送也可以分开多次接收。
2.2.2数据报套接字-UDP
UDPUser Datagram Protocol用户数据报协议传输层协议。
特点无连接不可靠传输面向数据报有接受缓冲区无发送缓冲区大小受限一次最多传输64K全双工。
类似于发微信
对于数据报来说可以简单理解为传输数据是一块一块的发送一块数据假如有100个字节必须一次发送接收的也必须是100个字节而不能分100次每次接收一个字节。
拓展关于网速快慢
“木桶原理” 在网络通信的过程中有很多路由器、交换机。转发能力存在上限转发的不止是一个用户的数据。某个设备达到转发能力的上限就会卡顿丢包。
2.3Java数据报套接字通信模型
对于UDP协议来说具有无连接面向数据报的特征即每次都是没有建立连接并且一次会发送全部数据报。一次接收全部数据报。
Java中使用UDP协议通信主要基于DatagramSocket类来创建数据报套接字并使用DatagramPacket作为发送或接收的UDP数据报对于一次发送及接收UDP数据报的流程如下 以上只是一次发送端的UDP数据报发送及接收端的数据报接收并没有返回的数据也就是只有请求没有响应。对于一个服务器来说重要的是提供多个客户端的请求及响应。
下面实现一个最简单的UDP版本的客户端服务器程序--回显服务器echo serve
2.4UDP数据报套接字编程
一个普通的服务器收到请求根据请求计算响应返回响应。
echo serve:省略了其中的”根据请求计算响应“请求是啥就返回啥这个代码没有实际的业务也没有太大作用和意义只是为了展示socket api 基本用法但是对于一个服务器来说一定”根据请求计算响应“这个环节是最重要的。
2.4.1DatagramSocket API
使用这个类表示一个socket对象。【在操作系统中把socket对象也是当作一个文件来处理的相当于是文件描述符表中的一项】普通文件对应硬盘设备socket文件对应网卡。
1个socket对象就可以和另外一台主机进行通信如果需要多个不同主机通信则需要创建多个socket对象。
DatagramScocket是UDP Socket用于发送和接收UDP数据报。 socket通常也称作套接字用于描述IP地址和端口是一个通信链的句柄。
数据报(Data gram),通过网络传输的数据的基本单元包含一个报头header和数据本身其中报头描述了数据的目的地以及和其它数据之间的关系。 完备的、独立的数据实体该实体携带要从源计算机传递到目的计算机的信息该信息不依赖以前在源计算机和目的计算机以及传输网络间交换。 DatagramSocket构造方法 方法签名方法说明DatagramSocket()创建一个UDP数据报套接字的Socket绑定到本机任意一个随机端口一般用于客户端DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口一般用于服务器 DatagramSocket方法 方法签名方法说明 void receive(DatagramPacket p) 此处传入的相当于是一个空对象receive方法内部会对参数的这个空对象进行内容填充从而构造出结果数据参数也是一个”输出型参数“ 从此套接字接收数据报如果没有接收到数据报该方法会阻塞等待void send(Datagram Packet p)从此套接字发送数据报不会阻塞等待直接发送void close关闭此数据报套接字
2.4.2DatagramPacket API
DatagramPacket是UDP Socket发送和接收的数据报表示UDP中传输的一个报文。 DatagramPacket构造方法 方法签名方法说明 DatagramPacket(byte buf ,int length) 把buf这个缓冲区给设置进去了 构造一个DatagramPacket以用来接收数据报接收的数据保存在字节数组第一个参数buf中接收指定长度第二个参数length DatagramPacket(byte[ ] buf,int offset,int length,SocketAddress address) Socket Address Ip端口号 构造一个DatagramSocketPacket以用来发送数据报发送的数据为字节数组第一个参数buf中从0到指定长度第二个参数length。address指定目的主机的IP和端口号。 DatagramPacket方法 方法签名方法说明InetAddress getAddress()从接收的数据报中获取发送端主机IP地址或从发送的数据报中获取接收端主机IP地址。int getPort() 从接收端的数据报中获取发送端主机的端口号或从发送的数据报中获取接收端主机端口号。 byte[ ] getData()获取数据报中的数据
构造UDP发送的数据时需要传入socketAddress该对象可以使用InetSocketAddress来创建。
2.4.3InetSocketAddress API InetSocketAddress(Socket Address 的子类)构造方法 方法签名方法说明InetSocketAddress(InetAddress addr,int port)创建一个Socket地址包含IP地址和端口号。
2.4.4服务器代码实现
核心思想
1读取请求并解析
2根据请求计算响应
3构造响应并写回给客户端
数据到达网卡经过内核的层层分用最终到达UDP传输层协议。
调用receive相当于执行到内核中的相关udp代码就会把这个udp数据报里面载荷部分取出来拷贝到用户提供的byte[ ]数组中。
代码实现
package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;//UDP版本的回显服务器
public class UdpEcSe {private DatagramSocket socket null;public UdpEcSe(int port) throws SocketException {socket new DatagramSocket(port);}public void start() throws IOException {System.out.println(服务器启动);while (true){//1.读取客户端发来的请求是啥DatagramPacket requestPacket new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//通过receive方法来读取请求,receive内部会针对参数对象填充数据。填充的数据来自于网卡String request new String(requestPacket.getData(),0, requestPacket.getLength());//2.根据请求计算响应此处是一个回显服务器所以请求和响应是相同的String response process(request);//3.将响应写回客户端,需要用到send方法DatagramPacket responsePacket new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(requestPacket);//4.打印一下当前这次请求响应的处理中间结果System.out.printf([%s:%d] req: %s;resp:%s\n,requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}public String process(String request){return request;}public static void main(String[] args) throws IOException {UdpEcSe server new UdpEcSe(9090);server.start();}}
加注释版本
package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;/*** Created with IntelliJ IDEA.* Description:* User: 苏西西* Date: 2023-10-18* Time: 14:59*/
//UDP版本的回显服务器
public class UdpEcSe {//首先需要创建一个成员//网络编程首先是要操作网卡网卡不方便直接操作// 在操作系统内核中使用了一种特殊的叫做“socket”这样的文件来抽象表示网卡//因此进行网络通信需要先有一个对象private DatagramSocket socket null;//构造方法将对象实例化//对于服务器来说创建的同时还需要关联上一个端口号//服务器是网络传输中被动的一方如果是操作系统随机分配的端口public UdpEcSe(int port) throws SocketException {socket new DatagramSocket(port);}//启动服务器public void start() throws IOException {System.out.println(服务器启动);//服务器不是只给一个客户端提供服务需要去服务很多客户端while (true){//只要有客户端过来就可以提供服务//1.读取客户端发来的请求是啥//对于UDP来说传输数据的基本单位是DatagramPacket//receive方法的参数是一个输出型参数需要先构造好一个空白的DatagramPacket对象交给receive 来进行填充//DatagramPacket相当于是在点餐的时候给顾客一个空白的纸条客户写完之后商家再根据纸条的需求来做食物DatagramPacket requestPacket new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//通过receive方法来读取请求,receive内部会针对参数对象填充数据。填充的数据来自于网卡//此时这个DatagramPacket 是一个特殊的对象并不方便直接进行处理//可以将这里包含的数据拿出来构造一个字符串//字节数组作为存储数据的缓冲区此处给的最大的长度是4096但是这里的空间不一定会被用满可能只使用小部分//因此构造字符串哪些用了构造那部分就可以通过getLength获取到实际的数据报的长度//只把这个实际有效部分给构造成字符串即可String request new String(requestPacket.getData(),0, requestPacket.getLength());//2.根据请求计算响应此处是一个回显服务器所以请求和响应是相同的String response process(request);//3.将响应写回客户端,需要用到send方法// send的参数也是一个DatagramPacket需要将这个对象构造好//这里也需要通过字节数组进行构造不同的是读请求是需要构造一个空的字节数组//读响应的字节数组就不能是空的了得带有respose里面的内容--响应内容//需要注意的是response.getBytes().length是计算字节的个数这里不能写作response.length() 【字符的个数】//DatagramPacket只认字节不认字符。DatagramPacket responsePacket new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(requestPacket);//4.打印一下当前这次请求响应的处理中间结果System.out.printf([%s:%d] req: %s;resp:%s\n,requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}//根据请求计算响应//如果不是回显服务器则可以在process中灵活的进行处理public String process(String request){return request;}public static void main(String[] args) throws IOException {//端口号指定可以在1024-65535范围内随便挑一个数字UdpEcSe server new UdpEcSe(9090);server.start();}}需要强调的内容 2.4.5客户端代码实现
核心思想
1从控制台读取一个要发送的数据 2把这个数据构造成一个UDP的请求并发送 3读取服务器的 UDP 响应并解析 4把解析好的结果显示出来
代码实现
package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;//UDP版本的回显客户端
public class UdpEcCl {private DatagramSocket socket null;private String serverIp null;private int serverPort 0;public UdpEcCl(String serverIp,int serverPort) throws SocketException {socket new DatagramSocket();this.serverIp serverIp;this.serverPort serverPort;}public void start() throws IOException {System.out.println(客户端启动);Scanner scanner new Scanner(System.in);while (true){//1.从控制台读取一个要发送的数据System.out.print();String request scanner.next();if(request.equals(exit)){System.out.println(bye);break;}//2.把这个数据构造成一个UDP的请求并发送DatagramPacket requestPacket new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);//3.读取服务器的 UDP 响应并解析DatagramPacket responsePacket new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//4.把解析好的结果显示出来String response new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEcCl clinet new UdpEcCl(127.0.0.1,9090);clinet.start();}}加注释版本
package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;//UDP版本的回显客户端
public class UdpEcCl {//1.首先需要创建出来一个socket对象//网络编程需要操控网卡就需要创建一个socket对象进行远程操控private DatagramSocket socket null;//需要将ip和端口存一下private String serverIp null;private int serverPort 0;//写一个构造方法//指定服务器的ip和服务器的端口一次通信需要有俩ip俩端口//客户端的ip是127.0.0.1端口是系统自动分配的//服务器的ip和端口也需要告诉客户端才能顺利将消息发给服务器public UdpEcCl(String serverIp,int serverPort) throws SocketException {socket new DatagramSocket();this.serverIp serverIp;this.serverPort serverPort;}public void start() throws IOException {System.out.println(客户端启动);Scanner scanner new Scanner(System.in);while (true){//1.从控制台读取一个要发送的数据System.out.print();//客户端发送的请求String request scanner.next();//对客户端输入的内容进行进行简单的翻译if(request.equals(exit)){System.out.println(bye);break;}//2.把这个数据构造成一个UDP的请求并发送//构造这个packet的时候需要把serverIp和port都传入过来// 但是由于此处的ip地址需要填写的是32位的整数形式//上述的IP地址是一个字符串需要使用 InetAddress.getByName()来进行转换DatagramPacket requestPacket new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);//3.读取服务器的 UDP 响应并解析DatagramPacket responsePacket new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//4.把解析好的结果显示出来String response new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEcCl clinet new UdpEcCl(127.0.0.1,9090);clinet.start();}}理解服务器与客户端端口
对于服务器来说端口必须是确定好的对于客户端来说端口是可以系统分配的。
来食堂买饭商家给顾客的小票就相当于是端口号小票上的编号究竟是多少也是想当于是随机的控制不了。就想在客户端这里手动指定端口是可行的但是并不推荐这样。有可能指定的这个号码会被别人用了。
客户端如果显示指定端口就有可能和客户端电脑上的其他程序的端口就冲突了这一冲突就可能会导致程序没有办法正常通信了。
那么为什么服务器这边指定的端口不怕重复呢
服务器是程序员自己手里的机器上面运行什么都是程序员可控的程序员就可以安排哪个程序使用哪个端口客户端的机器是在用户的手里上面运行的程序也是不同的是不可控的。
2.4.6服务器和客户端执行顺序
一定是服务器先运行。服务器是被动的一方类比于我们要去餐馆吃饭一定是饭店先开门才能去吃饭。
第一步服务器执行到receive进行阻塞。
第二步客户端执行客户端读取用户输入的内容。
第三步客户端发送请求。
第四步客户端等待响应。服务器收到请求进行返回。【可以认为这两部分相同的时间执行的】
第五步服务器根据请求计算响应。process
第六步服务器执行send返回响应。
第七步客户端receive从阻塞中返回读到响应
对于客户端服务器程序来说一个客户端要给很多个服务器提供服务也就需要构造出多个客户端来进行测试。
2.4.7IDEA多个客户端设置操作 2.4.8客户端服务器执行结果