网络编程套接字

2024-06-04 2465阅读

文章目录

  • 一、前言
    • 为什么需要网络编程?
    • 二、网络编程是什么?
    • 三、网络编程的基本概念
      • 3.1发送端和接收端
      • 3.2请求和响应
      • 3.3服务器和客户端
      • 四、常见的服务端客户端模型
      • 五、Socket套接字
        • 5.1概念
        • 5.2分类
        • 六、数据报套接字通信模型
        • 七、Java流套接字通信模型
        • 八、UDP数据报套接字
          • API介绍
          • 九、TCP流套接字
            • API介绍

              一、前言

              网络编程套接字 第1张

              在本文中,会介绍一些关于网络编程的基础知识
              Socket的一些api
              会在文章末尾运用所讲知识做一个基于网络的回显的代码
              

              为什么需要网络编程?

              当你打开CSDN看到这篇文章时,实质上是通过网络来获取一个文本资源、图片资源等等

              和本地硬盘上打开一个文本一样,只不过这个文本资源是来自于网络。

              和本地资源来说,网络提供了更多更丰富的资源。

              所谓的网络资源,就是在网络中可以获取到的各种资源。

              而所有的网络资源,都是通过网络编程来传输的。

              二、网络编程是什么?

              网络编程,是指网络上的主机,通过不同的进程,以编程的方式来实现网络传输(实现网络数据传输)

              网络编程套接字 第2张

              这里只需要满足不同进程就可以,因为在大多数的情况下,都是在同一个主机上,通过网络编程来传输数据。

              三、网络编程的基本概念

              3.1发送端和接收端

              在⼀次⽹络数据传输时:

              发送端: 数据的发送⽅进程,称为发送端。发送端主机即⽹络通信中的源主机。

              接收端: 数据的接收⽅进程,称为接收端。接收端主机即⽹络通信中的⽬的主机。

              收发端: 发送端和接收端两端,也简称为收发端。

              注意:发送端和接收端是相对的,只是一次网络数据传输产生数据流向后的概念。

              网络编程套接字 第3张

              3.2请求和响应

              一般来说,获取一个网络资源,一般需要两次网络数据传输。

              • 第一次:请求数据的发送
              • 第二次:响应数据的发送

                网络编程套接字 第4张

                3.3服务器和客户端

                服务端: 在网络传输中,提供服务的一方进程,成为服务端。也可以向外提供服务

                客户端: 获取服务的一方进程,称为客户端。

                • 客户端获取服务资源!

                  网络编程套接字 第5张

                  • 客户端保存资源在服务端

                    网络编程套接字 第6张

                    四、常见的服务端客户端模型

                    一般来说,网络数据的传输的过程如下

                    • 客户端:输入请求,将请求发送到服务端
                    • 服务端:接收请求,分析请求内容
                    • 服务端:根据请求内容执行响应的业务
                    • 服务端:将执行业务的结果作为响应返回给客户端
                    • 客户端:根据服务端的响应,将响应展示出来

                      五、Socket套接字

                      5.1概念

                      Socket套接字,是由系统提供⽤于⽹络通信的技术,是基于TCP/IP协议的⽹络通信的基本操作单元。

                      基于Socket套接字的⽹络程序开发就是⽹络编程。

                      5.2分类

                      Socket套接字主要针对传输层协议分为三类:

                      1. 流套接字

                        流套接字: 使用传输层Tcp协议

                        TCP,即Transmission Control Protocol(传输控制协议),传输层协议。

                        下一位Tcp的特点

                      • 有连接
                      • 可靠传输
                      • 面向字节流
                      • 有接收缓冲区,也有发送缓冲区
                      • 大小不限

                        对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是⽆边界的数据,可以多次发送,也可以分开多次接收。

                        2. 数据报套接字

                        数据报套接字: 使⽤传输层UDP协议

                        UDP,即User Datagram Protocol(⽤⼾数据报协议),传输层协议。

                        以下为UDP的特点:

                        • 无连接
                        • 不可靠传输
                        • 面向数据报
                        • 有接收缓冲区,无发送缓冲区
                        • 大小受限:一次最多传输64K

                          对于数据报来说,可以简单的理解为,传输数据是⼀块⼀块的,发送⼀块数据假如100个字节,必须⼀次发送,接收也必须⼀次接收100个字节,⽽不能分100次,每次接收1个字节。

                          3. 原始套接字

                          原始套接字⽤于⾃定义传输层协议,⽤于读写内核没有处理的IP协议数据。

                          六、数据报套接字通信模型

                          对于UDP协议来说,具有⽆连接,⾯向数据报的特征,即每次都是没有建⽴连接,并且⼀次发送全部数据报,⼀次接收全部的数据报。

                          java中使⽤UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使⽤DatagramPacket 作为发送或接收的UDP数据报。对于⼀次发送及接收UDP数据报的流程如下:

                          网络编程套接字 第7张

                          七、Java流套接字通信模型

                          网络编程套接字 第8张

                          八、UDP数据报套接字

                          API介绍

                          DatagramSocket

                          DatagramSocket 是UDP Socket,⽤于发送和接收UDP数据报。

                          方法签名方法说明
                          DatagramSocket()创建⼀个UDP数据报套接字的Socket,绑定到本机任意⼀个随机端⼝(⼀般⽤于客⼾端)
                          DatagramSocket(int port)创建⼀个UDP数据报套接字的Socket,绑定到本机指定的端⼝(⼀般⽤于服务端)

                          DatagramSocket ⽅法:

                          方法签名方法说明
                          void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该⽅法会阻塞等待)
                          void send(DatagramPacket p)从此套接字发送数据报包(不会阻塞等待,直接发送)
                          void close()关闭此数据报套接字

                          DatagramPacket

                          DatagramPacket是UDP Socket发送和接收的数据报。

                          DatagramPacket 构造⽅法:

                          方法签名方法说明
                          DatagramPacket(byte[] buf, int length)构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)
                          DatagramPacket(byte[] buf, int offset, int length构造⼀个DatagramPacket以⽤来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从0到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP和端⼝号

                          DatagramPacket ⽅法:

                          方法签名方法说明
                          InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
                          int getPort()从从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号
                          byte[] getData()获取数据报中的数据

                          构造UDP发送的数据报时,需要传⼊ SocketAddress ,该对象可以使⽤ InetSocketAddress来创建。

                          InetSocketAddress

                          InetSocketAddress ( SocketAddress 的⼦类 )构造⽅法:

                          方法签名方法说明
                          InetSocketAddress(InetAddress addr, int port)创建⼀个Socket地址,包含IP地址和端⼝号

                          利用UDP数据报创建一个回显客户端和服务器

                          public class UdpEchoClient {
                              private DatagramSocket socket = null;
                              private String serverIp;
                              private int serverPort;
                              public UdpEchoClient(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){
                                      System.out.println("请输入你的请求!!!");
                                      String request = scanner.next();
                                      //打包成数据包 通过网卡发送到服务端
                                      DatagramPacket requestPackage = new DatagramPacket(request.getBytes(),0,request.getBytes().length,
                                              InetAddress.getByName(serverIp),serverPort);
                                      socket.send(requestPackage);
                                      DatagramPacket responsePackage = new DatagramPacket(new byte[4096],4096);
                                      socket.receive(responsePackage);
                                      String response = new String(responsePackage.getData(),0,responsePackage.getLength());
                                      System.out.println(response);
                                  }
                              }
                              public static void main(String[] args) throws IOException {
                                  UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);
                                  client.start();
                              }
                          
                          public abstract class UdpEchoServer {
                              private DatagramSocket socket = null;
                              public UdpEchoServer(int port) throws SocketException {
                                  socket = new DatagramSocket(port);
                              }
                              public void start() throws IOException {
                                  System.out.println("服务器启动!!!");
                                  //接收请求
                                  while (true){
                                      DatagramPacket requestPackage = new DatagramPacket(new byte[4096],4096);
                                      socket.receive(requestPackage);
                                      //处理请求
                                      String request = new String(requestPackage.getData(),0,requestPackage.getLength());
                                      String response = process(request);
                                      //返回响应
                                      DatagramPacket responsePackage = new DatagramPacket(response.getBytes(),0,response.getBytes().length,
                                              requestPackage.getSocketAddress());
                                      socket.send(responsePackage);
                                      System.out.printf("[%s:%d] req=%s res=%s\n",requestPackage.getAddress(),requestPackage.getPort(),request,response);
                                  }
                              }
                              public String process(String request) {
                                  return request;
                              }
                              public static void main(String[] args) throws IOException {
                                  UdpEchoServer server = new UdpDictServer(9090);
                                  server.start();
                              }
                          }
                          

                          运行效果如下

                          网络编程套接字 第9张

                          网络编程套接字 第10张

                          一个简易的字典

                          public class UdpDictServer extends UdpEchoServer{
                              private HashMap hashMap = null;
                              public UdpDictServer(int port) throws SocketException {
                                  super(port);
                                  hashMap = new HashMap();
                                  hashMap.put("hello","你好" );
                                  hashMap.put("dog","小狗" );
                                  hashMap.put("cat","小猫" );
                                  hashMap.put("world","世界" );
                                  hashMap.put("baby","宝贝" );
                              }
                              @Override
                              public String process(String request){
                                   return hashMap.getOrDefault(request,"没有找到该词汇");
                              }
                              public static void main(String[] args) throws IOException {
                                  UdpDictServer dictServer = new UdpDictServer(9090);
                                  dictServer.start();
                              }
                          }
                          

                          网络编程套接字 第11张

                          网络编程套接字 第12张

                          九、TCP流套接字

                          API介绍

                          ServerSocket

                          ServerSocket 是创建TCP服务端Socket的API。

                          ServerSocket 构造⽅法:

                          方法签名方法说明
                          ServerSocket(int port)创建⼀个服务端流套接字Socket,并绑定到指定端⼝

                          ServerSocket ⽅法:

                          方法签名方法说明
                          Socket accept()开始监听指定端⼝(创建时绑定的端⼝),有客⼾端连接后,返回⼀个服务端Socket对象,并基于该Socket建⽴与客⼾端的连接,否则阻塞等待
                          void close()关闭此套接字

                          Socket

                          Socket 是客⼾端Socket,或服务端中接收到客⼾端建⽴连接(accept⽅法)的请求后,返回的服务端Socket。

                          不管是客⼾端还是服务端Socket,都是双⽅建⽴连接以后,保存的对端信息,及⽤来与对⽅收发数据的。

                          Socket 构造⽅法

                          方法签名方法说明
                          Socket(String host, int port)创建⼀个客⼾端流套接字Socket,并与对应IP的主机上,对应端⼝的进程建⽴连接

                          Socket ⽅法:

                          方法签名方法说明
                          InetAddress getInetAddress()返回套接字所连接的地址
                          InputStream getInputStream()返回此套接字的输⼊流
                          OutputStream getOutputStream()返回此套接字的输出流
                          public class TcpEchoServer {
                              private ServerSocket serverSocket = null;
                              public TcpEchoServer(int port) throws IOException {
                                  serverSocket = new ServerSocket(port);
                              }
                              public void start() throws IOException {
                                  System.out.println("服务端启动!!!");
                          //        ExecutorService pool = Executors.newCachedThreadPool();
                                  while (true){
                                      Socket clientSocket = serverSocket.accept();
                                      Thread t = new Thread(()->{
                                          try {
                                              processConnection(clientSocket);
                                          } catch (IOException e) {
                                              throw new RuntimeException(e);
                                          }
                                      });
                                      t.start();
                                  }
                              }
                              private void processConnection(Socket clientSocket) throws IOException {
                                  System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress(),clientSocket.getPort());
                                  try (InputStream inputStream = clientSocket.getInputStream();
                                       OutputStream outputStream = clientSocket.getOutputStream()){
                                      Scanner scanner = new Scanner(inputStream);
                                      while (true){
                                          if (!scanner.hasNext()){
                                              System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress(),clientSocket.getPort());
                                              break;
                                          }
                                          String request = scanner.next();
                                          String response = process(request);
                                          outputStream.write(response.getBytes(),0,response.getBytes().length);
                                          System.out.printf("[%s:%d] req=%s res=%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);
                                      }
                                  } catch (IOException e) {
                                      throw new RuntimeException(e);
                                  }
                              }
                              public String process(String request) {
                                  return request +"\n";
                              }
                              public static void main(String[] args) throws IOException {
                                  TcpEchoServer server = new TcpEchoServer(9090);
                                  server.start();
                              }
                          }
                          
                          public class TcpEchoClient {
                             private Socket socket = null;
                             public TcpEchoClient(String serverIp,int serverPort) throws IOException {
                                 socket = new Socket(serverIp,serverPort);
                             }
                             public void start(){
                                 System.out.println("客户端启动!");
                                 Scanner scanner = new Scanner(System.in);
                                 try (InputStream inputStream = socket.getInputStream();
                                      OutputStream outputStream = socket.getOutputStream()){
                                     Scanner scannerNetwork = new Scanner(inputStream);
                                     while (true){
                                         System.out.println("输入你的请求-》");
                                         String request = scanner.next();
                                         request +="\n";
                                         outputStream.write(request.getBytes());
                                         if (!scannerNetwork.hasNext()){
                                             break;
                                         }
                                         String response = scannerNetwork.next();
                                         System.out.println(response);
                                     }
                                 } catch (IOException e) {
                                     throw new RuntimeException(e);
                                 }
                             }
                              public static void main(String[] args) throws IOException {
                                  TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);
                                  client.start();
                              }
                          }
                          

                          运行效果展示

                          网络编程套接字 第13张

                          网络编程套接字 第14张


                          以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]