网络编程实操8小案例

2022-12-04 16:10:07 浏览数 (3)

网络编程简介

/** * @brief * 网络编程 三大组件 * * 1, IP : 最大字节255, 默认得 127.0.0.1 ,ping不通网卡出问题了 * ipv4: 四段得ip, ipv6: 四段不够用了,定义了六段得 * 网络中设备得标识:不容易记忆,可用主机名,本地回环地址:127.0。0.1 主机名:localhost * * $ ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=1.39 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.029 ms * * 2,逻辑端口 0-65535 (0-1024被占用了,最好不用)web:8080 可以改 * * 3,通信规则 tcp/ip ,udp * * OSI参考模型 * TCP/IP参考模型 * $ javac Inet.java Command 'javac' not found, but can be installed with: sudo apt install openjdk-11-jdk-headless # version 11.0.15 10-0ubuntu0.20.04.1, or sudo apt install default-jdk # version 2:1.11-72 sudo apt install openjdk-16-jdk-headless # version 16.0.1 9-1~20.04 sudo apt install openjdk-17-jdk-headless # version 17.0.3 7-0ubuntu0.20.04.1 sudo apt install openjdk-8-jdk-headless # version 8u312-b07-0ubuntu1~20.04 sudo apt install openjdk-13-jdk-headless # version 13.0.7 5-0ubuntu1~20.04 sudo apt install ecj # version 3.16.0-1 * * $ uname -rs Linux 5.10.16.3-microsoft-standard-WSL2 $ cat /etc/issue Ubuntu 20.04.4 LTS n l * * UDP : 聊天,视频会议 * 1,将数据及源目的封装成数据包,不需要建立连接 * 2,每个数据包的大小限制在 64K 内 * 3,没有连接,因此是不可靠的 * 4,不需要建立连接,速度快 * * TCP:120打电话,下载 * 1,建立连接,形成传输数据的通道 * 2,在连接中进行大数据传输 * 3,通过三次握手完成连接,是可靠协议 * 4,必须建立连接,效率会低 * * Socket * 1,socket为网络服务提供一种机制 * 2,通信的两端都有socket * 3,网络通信其实就是socket间的通信 * 4,数据在两个socket间通过IO传输 */

UDP案例

案例1:UDP传输

Send端

代码语言:javascript复制
//UDP传输 Send
class IPDemo
{
   public static void main(String[] args) throws Exception
   {
      //获取本机
      InetAddress i = InetAddress.getLocalHost();
      System.out.println(i.toString());
      System.out.println("address: " i.getHostAddress());
      System.out.println("name: " i.getHostName());

      //获取任意机器
      //不在同一网段,解析不出名字
      InetAddress ia = InetAddress.getByName("www.baidu.com");//www.baidu.com
      System.out.println(ia.toString());
      System.out.println("address: " ia.getHostAddress());
      System.out.println("name: " ia.getHostName());

      //UDP send
      /**
       * 思路:
       * 1,建立udpsocket服务
       * 2,提供数据,并将数据封装到数据包中
       * 3,通过socket服务的发生功能将数据包发出去
       * 4,关闭资源
       */
      //1, 创建 udp服务,通过 DatagramSocket对象
      DatagramSocket ds = new DatagramSocket();
      //2,确定数据,并封装成数据包
      byte[] buf = "udp ge men lai le".getBytes();
      DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("172.29.194.96"),10000);
      //3,通过socket服务,将已有的数据包发生出去,通过send方法
      ds.send(dp);
      //4, 关闭资源
      ds.close();
   }
}

Rece端

代码语言:javascript复制
class IPRece
{
   public static void main(String[] args) throws Exception
   {
      
      //UDP rece
      //1, 创建 udp服务,建立端点,通常会监听一个端口
      DatagramSocket ds = new DatagramSocket(10000);

      while(true)
      {
         //2, 定义数据包,用来存储数据
         byte[] buf = new byte[1024];
         DatagramPacket dp = new DatagramPacket(buf,buf.length);
         //3,通过 receive方法将收到数据存入数据包中
         ds.receive(dp);
         //4, 通过数据包的方法获取其中的数据
         String ip = dp.getAddress().getHostAddress();
         String data = new String(dp.getData(),0,dp.getLength());
         int port = dp.getPort();
         System.out.println(ip "::" data "::" port);
      }
       //5,关闭资源
      //ds.close();
   }
}

案例2:键盘录入

Send端

代码语言:javascript复制
//键盘录入
class UdpSend
{
   public static void main(String[] args) throws Exception
   {
      DatagramSocket ds = new DatagramSocket();

      BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

      String line = null;

      while((line = bufr.readLine()) != null)
      {
         if("886".equals(line))
            break;

         byte[] buf = line.getBytes();

         DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("172.29.194.96"),10001);

         ds.send(dp);
      }
      ds.close();
   }
}

Rece端

代码语言:javascript复制
class UdpRece
{
   public static void main(String[] args) throws Exception
   {
      DatagramSocket ds =new DatagramSocket(10001);
      while(true)
      {
         byte[] buf = new byte[1024];
         DatagramPacket dp = new DatagramPacket(buf,buf.length);

         ds.receive(dp);
         String ip = dp.getAddress().getHostAddress();
         String data = new String(dp.getData(),0,dp.getLength());
         System.out.println(ip "::" data);
      }
   }
}

案例3:聊天系统

Send端 多线程定义:是个模板

代码语言:javascript复制
class Send implements Runnable
{
   private DatagramSocket ds;
   public Send(DatagramSocket ds)
   {
      this.ds = ds;
   }
   
   public void run()
   {
      try 
      {
         DatagramSocket ds = new DatagramSocket();

         BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
   
         String line = null;
   
         while((line = bufr.readLine()) != null)
         {
            if("886".equals(line))
               break;
   
            byte[] buf = line.getBytes();
   
            DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("172.29.194.96"),10001);
   
            ds.send(dp);
        } 
      }
      catch (Exception e) 
      {
         throw new RuntimeException("send fail");
      }
   }
}

Rece端 多线程定义:是个模板

代码语言:javascript复制
class Rece implements Runnable
{
   private DatagramSocket ds;
   public Rece(DatagramSocket ds)
   {
      this.ds = ds;
   }
   
   public void run()
   {
      try 
      {
         while(true)
         {
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf,buf.length);

            ds.receive(dp);
            String ip = dp.getAddress().getHostAddress();
            String data = new String(dp.getData(),0,dp.getLength());
            System.out.println(ip "::" data);
         }
         
      }
      catch (Exception e) 
      {
         throw new RuntimeException("rece fail");
      }
   }
}

调用

代码语言:javascript复制
class ChatDemo
{
   public static void main(String[] args) throws Exception
   {
      DatagramSocket sendSocker = new DatagramSocket();
      DatagramSocket receSocker = new DatagramSocket(10001);

      new Thread(new Send(sendSocker)).start();
      new Thread(new Rece(receSocker)).start();
   }
}

TCP案例

案例1:基本传输

//TCP传输 /** * 客户端Socket和服务端ServerSocket * 建立客户端和服务器端 * 建立连接后,通过Socket中的IO 流进行数据的传输 * 关闭socket * 同样,客户端与服务端是两个独立的应用程序 */ /** * 客户端: 通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机 因为tcp是面向连接的,所以在建立socket服务时,就要有服务端存在,并连接成功 形成通路后,在该通道进行数据的传输 */

client

代码语言:javascript复制
  class TcpClient
  {
      public static void main(String[] args) throws Exception
      {
         //创建客户端socket服务,指定目的主机和端口
         Socket s = new Socket("",10003);

         //为了发送数据,应该获取socket流中的输出流
         OutputStream out = s.getOutputStream();

         out.write("tcp ge men lai le".getBytes());

         //服务端返回信息
         InputStream in = s.getInputStream();
         byte[] buf = new byte[1024];
         int len = in.read(buf);
         System.out.println(new String(buf,0,len));

         s.close();
      }
  }

/** * 服务端: * 1,建立服务端的 socket服务,ServerSocket * 并监听一个端口 * 2,获取连接过来的客户端对象 * 通过 ServerSocket的accept方法,没有连续就会等,所以这个方法是阻塞的 * 3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到客户端对象的读取流来读取发过来的数据 * 4,关闭服务端 */

Server

代码语言:javascript复制
  class TcpServer
  {
      public static void main(String[] args) throws Exception
      {
         //建立服务端 socket服务,并监听一个端口
         ServerSocket ss = new ServerSocket(10003);
         //通过accept方法获取连接过来的客户端对象
         Socket s = ss.accept();

         String ip = s.getInetAddress().getHostAddress();
         System.out.println(ip "....connected");

         //获取客户端发送来的数据,使用客户端对象的读取来读取数据
         InputStream in = s.getInputStream();

         byte[] buf = new byte[1024];
         int len = in.read(buf);//阻塞的

         System.out.println(new String(buf,0,len));

         //给客户端反馈信息
         OutputStream out = s.getOutputStream();
         Thread.sleep(10000);
         out.write("rece !".getBytes());
         s.close();
         ss.close();
      }
  }

案例2:文本转换器

* * 建立一个文本转换器,客户端给服务端发送文本,服务端会将文本转成大写返回给客户端, * 而且客户端可以不断地进行文本转换,当客户端输入 over时,转换结束 * *步骤: 1,建立服务 2,获取键盘输入 3,将数据发送服务端 4,获取服务端返回地大写数据 5,结束,关资源 都是文本,用IO,提高效率 ,加入缓冲 */

client

代码语言:javascript复制
class TransClient
{
   public static void main(String[] args) throws Exception
   {
      Socket s =new Socket("127.0.1.1",10006);

      //定义读取键盘数据地流对象
      BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

      //定义目的,将数据写入到 socket输出流,发送服务端
      BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

      //定义一个socket读取流,读取服务端返回地大写信息
      BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

      String line = null;
      while((line = bufr.readLine()) != null)
      {
         if("over".equals(line))
            break;

         bufOut.write(line);
         bufOut.newLine();//换行
         //数据写入缓冲区进行刷新
         bufOut.flush();



         String str = bufIn.readLine();
         System.out.println("server: " str);
      }

      bufr.close();
      s.close();
   
   }
}

Server

代码语言:javascript复制
class TransServer
{
   public static void main(String[] args) throws Exception
   {
      ServerSocket ss = new ServerSocket(10006);
      Socket s = ss.accept();

      String ip = s.getInetAddress().getHostAddress();
      System.out.println(ip "....connected");

      //读取socket读取流中地数据
      BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

      //定义目的,socket输出流,将大写数据写入到 socket输出流,并发送给客户端
      BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
      
      //替换上面一行
      //PrintWrite out = new PrintWrite(s.getOutputStream,true);

      String line = null;
      while((line = bufIn.readLine()) != null)
      {  
         System.out.println(line);
         bufOut.write(line.toUpperCase());
         bufOut.newLine();//换行
         bufOut.flush();

         //替换上面三行
        // out.println(line.toUpperCase());
      }
      s.close();
      ss.close();
   
   }
}

/** * 出现问题: * 客户端和服务端都在莫名等待 * * 原因: * 因为客户端和服务端都有阻塞方法,这些方法没得读到结束标记,一直在等待,导致两端都在等待 */

案例3:图片传输

/** * 客户端: 1,服务端点 2,读取客户端已有的图片数据 3,通过 socket 输出流将数据发给服务端 4,读取服务端反馈信息 5,关闭 */

client

代码语言:javascript复制
class PicClient
{
   public static void main(String[] args) throws Exception
   {  
      if (args.length != 1)
      {
         System.out.println("select one jpg img");
         return;
      }
      File file = new File(args[0]);
      if (!(file.exists() && file.isFile()))
      {
         System.out.println("file not ok");
         return;
      }
      if (!file.getName().endsWith(".jpg"))
      {
         System.out.print("geshi img not ok");
         return;
      }

      if (file.length() > 1024*1024*5)
      {
         System.out.println("big");
         return;
      }


      Socket s =new Socket("127.0.1.1",8003);
      FileInputStream fis = new FileInputStream(file);
      OutputStream out = s.getOutputStream();
      byte[] buf = new byte[1024];
      int len = 0;
      while((len = fis.read(buf)) != -1)
      {
         out.write(buf,0,len);
      }

      InputStream in = s.getInputStream();

      byte[] bufIn = new byte[1024];
      int num = in.read(bufIn);
      System.out.println(new String(bufIn,0,num));

      fis.close();
      s.close();
   }
}

/**服务端 * * 这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程 * 这是B客户端连接,只有等待。 * 因为服务端还没有处理完A客户端的请求,还有循环回来执行下次 accept方法,所以暂时 * 获取不到B客户端对象 * * 那么为了可以让多个客户端同时并发访问服务端 * 服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求 * 如何定义线程? * 只要明确了每一个客户端要在服务端执行的代码即可,将代码放入run中 */

代码语言:javascript复制
class PicThread implements Runnable
{
   private Socket s;
   PicThread(Socket s)
   {
      this.s = s;
   }
   public void run()
   {
      int count = 1;
      String ip = s.getInetAddress().getHostAddress();
      try
      {
         System.out.println(ip "...connected");
         InputStream in = s.getInputStream();
         File file = new File(ip "(" (count) ")" ".jpg");
         while(file.exists())
            file = new File(ip "(" (count  ) ")" ".jpg");

         FileOutputStream fos = new FileOutputStream(file);
   
         byte[] buf = new byte[1024];
         int len = 0;
         while((len = in.read(buf)) != -1)
         {
            fos.write(buf,0,len);
         }
   
         OutputStream out = s.getOutputStream();
         out.write("upload sucess".getBytes());
         fos.close();
         s.close();
         
      }
      catch(Exception e)
      {
         System.out.println(ip "...not connected");
      }
   }
}
class PicServer
{
   public static void main(String[] args) throws Exception
   {
      ServerSocket ss = new ServerSocket(8003);
      while(true)
      {  
         Socket s= ss.accept();
         
         new Thread(new PicThread(s)).start();
      }
    
      //ss.close();
   }
}

案例4:键盘录入

/*** * 需求分析: * 客户端通过键盘录入用户名 * 服务端对这个用户名进行校验 * * 如果该用户名存在,则在服务端显示XXX,已经登陆 * 并在客户端显示XXX 欢迎光临 * * 如果用户不存在,在服务端显示XXX,尝试登陆 * 并在客户端显示 XXX 该用户不存在 * * 最多就登录三次 */ client

代码语言:javascript复制
class LoginClient
{
   public static void main(String[] args) throws Exception
   {
     Socket s = new Socket("172.23.236.114",107);
     BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
     PrintWriter out = new PrintWriter(s.getOutputStream(),true);
     BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

     for(int x =0; x <3; x  )
     {
      String line = bufr.readLine();
      if(line == null)
         break;
      out.println(line);
      String info = bufIn.readLine();
    
      System.out.println("info:" info);

      if(info.contains("欢迎"))
         break;
     }

     bufr.close();
     s.close();
   }
}

//服务端封装原理模板

代码语言:javascript复制
//服务端封装原理模板
class UserThread implements Runnable
{
   private Socket s;
   UserThread(Socket s)
   {
      this.s = s;
   }
   public void run()
   {
      String ip = s.getInetAddress().getHostAddress();
      System.out.println(ip "....connected");
      try
      {
         for(int x=0; x<3;x  )
         {
            BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String name = bufIn.readLine();
            System.out.println(name "....name");
            if (name==null)
               break;
             
            BufferedReader bufr = new BufferedReader(new FileReader("2.txt.txt"));
       
            PrintWriter out = new PrintWriter(s.getOutputStream(),true);
            String line =null;
        
            boolean flag = false;

            while((line=bufr.readLine()) != null)
            {
               if(line.equals(name))
               {
                  flag = true;
                  break;
               }
            }

            if(flag)
            {
               System.out.println(name ",已登录");
               out.println(name ",欢迎光临");
            }
            else
            {
               System.out.println(name ",尝试登录");
               out.println(name ",用户名不正确");
            }
         }
         s.close();
      }
      catch(Exception e)
      {
         System.out.println(ip "...not connected");
      }
   }
}
class LoginServer
{
   public static void main(String[] args) throws Exception
   {
      ServerSocket ss = new ServerSocket(107);
      while(true)
      {
         Socket s= ss.accept();
         new Thread(new UserThread(s)).start();
      }
   }
}

案例5:浏览器客户端

/** * 客户端:浏览器 * 输入:https://172.23.236.114:11000/ * 或者终端输入:telnet 172.23.236.114 11000 * 服务端:自定义

*/

代码语言:javascript复制
class ServerDemo
{
   public static void main(String[] args) throws Exception
   {
      ServerSocket ss = new ServerSocket(11000);
      Socket s =ss.accept();
      System.out.println(s.getInetAddress().getHostAddress());

      PrintWriter out = new PrintWriter(s.getOutputStream(),true);

      out.println("<font color='red' size='7'>客户端你好<.font>");
      s.close();
      ss.close();
   }
}

1 人点赞