zoukankan      html  css  js  c++  java
  • java-网络编程

    1 网络模型

     

    2 网络通讯要素

    IP

    网络中的标识

    本地回环地址:127.0.01 主机名 localhost

    端口

    用于标识进程的逻辑地址,不同的进程的标识

    有效的端口0-65535  0-1024 系统使用或保留端口

     

     传输协议

    通讯的规则

    常见协议:TCP UDP

    UDP:对讲机

    TCP:打电话

     

    3 域名解析

     

     4 UDP

    1,发送时,创建待了送数据包pack,其中指定目标主机的ip地址和接收的端口

    调用DatagemSocket send(pack)方法发送pack数据报,发送端口由java绑定一个可用的端口

    2,接收时,创建指定的端口的DatagramScoket 调用基receve(pack)方法招收数据报接收的数据存放在pack包的缓冲区中,在调用pack.getData()方法获得里面的数据

    接收方必须指定接收端口,该接收端口正是发送数据包中指定的端口,而发送端口可以是任意一个可用的端口

    发送

    /*
             * 思路:
             * 1,建立udp的socket服务,
             * 2,将要发送的数据封装支数据包中去
             * 3,通过udp的socket服务将数据包发送出去
             * 4,关闭socket服务
             * 
             * */
            
            System.out.println("发送端启动");
            DatagramSocket ds = new DatagramSocket();
            
            
            String str= "我来了";
            byte [] buf = str.getBytes();
            
            DatagramPacket dp = 
                    new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10000);
            
            ds.send(dp);
            ds.close();

    接收

    /*
             * 接收端
             * 思路:
             * 1,建立scoket服务,因为要接收数据,必须要明确端口号
             * 2,创建数据包,用于存储接收到的数据,方便解析
             * 3.使用scoket服务的receive方法接收的数据存储到数据包中
             * 4,通过数据包的方法解析数据包的数据
             * 5.关闭资源
             * 
             * */
            
            
            System.out.println("接收启动");
            // 建立 udp scoket服务
            DatagramSocket ds = new DatagramSocket(10000);
            
            // 创建数据包
            byte [] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf,buf.length);
            
            // 使用接收方法
            ds.receive(dp);
            // 通过数据包的方法.解析数据.比如:地址,端口,数据内容
            String ip = dp.getAddress().getHostAddress();
            
            int port = dp.getPort();
             
            String text = new String (dp.getData(),0,dp.getLength());
            System.out.println(ip+":"+port+":" + text);
            
            ds.close();

    5 聊天程序

    发送端

    DatagramSocket ds = new DatagramSocket();
    
                      // 加上键盘录入
    
                      BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
    
                      String line = null;
    
                      while((line = bufr.readLine())!= null){
    
                              byte [] buf = line.getBytes();
    
                              DatagramPacket dp =
    
                                                new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10001);
    
                              ds.send(dp);
    
                              if("over".equals(line))
    
                                       break;
    
                      }

    接收端

    Whlie循环,让它一直接收
    
    
    上面是两个进程的工作,还要切换进程 ,可以创建两个线程,让它在五一个
    
    进程中.这时要用到线程技术

    发送端

    class Test implements Runnable {
    
             private DatagramSocket ds;
    
             public Test (DatagramSocket ds){
    
                      this.ds=ds;
    
             }
    
            
    
     
    
            
    
     
    
             @Override
    
             public void run() {
    
                      try{
    
                              System.out.println("发送端启动");
    
                     
    
                      // 加上键盘录入
    
                      BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
    
                      String line = null;
    
                      while((line = bufr.readLine())!= null){
    
                              byte [] buf = line.getBytes();
    
                              DatagramPacket dp =
    
                                                new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"), 10002);
    
                              ds.send(dp);
    
                              if("over".equals(line))
    
                                       break;
    
                      }
    
                      ds.close();
    
                      }catch(Exception e){
    
                             
    
                      }
    
                     
    
             }
    
    }

    接收端

    public class Test2 implements Runnable {
    
             private DatagramSocket ds ;
    
             public Test2(DatagramSocket ds){
    
                      this.ds=ds;
    
                      }
    
     
    
             @Override
    
             public void run() {
    
                      try{
    
                             
    
                             
    
                              while(true){
    
                              System.out.println("接收启动");
    
                              // 建立 udp scoket服务
    
                             
    
                              // 创建数据包
    
                              byte [] buf = new byte[1024];
    
                              DatagramPacket dp = new DatagramPacket(buf,buf.length);
    
                             
    
                              // 使用接收方法
    
                              ds.receive(dp);
    
                              // 通过数据包的方法.解析数据.比如:地址,端口,数据内容
    
                              String ip = dp.getAddress().getHostAddress();
    
                             
    
                              int port = dp.getPort();
    
                               
    
                              String text = new String (dp.getData(),0,dp.getLength());
    
                              System.out.println(ip+":"+port+":" + text);
    
                              }
    
                             
    
                      }catch(Exception e){
    
                             
    
                      }
    
                     
    
             }
    
            
    
    }

    数据测试

             public static void main(String[] args) throws SocketException {
    
     
    
                      DatagramSocket send = new DatagramSocket();
    
                      DatagramSocket rec = new DatagramSocket(10002);
    
                      Test s = new Test (send);
    
                      Test2 r = new Test2(rec);
    
                      new Thread(s).start();
    
                      new Thread(r).start();      

    6 TCP

    客户端

    // tcp传输.客户端建立过程
    
                      /*
    
                       *
    
                       * 1,创建tcp 客户端socket服务,使用的是scoket对象
    
                       * 2.如果连接建立成功,说明数据通道连接成功
    
                       *    可以通过getOutputSteam() 和getInputStream来获取两个字节流
    
                       * 3, 使用输出流 或者输入流
    
                       *
    
                       * */
    
                     
    
                      // 创建客户端服务
    
                      Socket socket = new Socket("127.0.0.1",20000);
    
                      //获取流
    
                      OutputStream out = socket.getOutputStream();
    
                     
    
                      // 使用输出流将指定的数据写出去
    
                      out.write("人的家".getBytes());
    
                      // 关闭资源
    
                      socket.close();                 

    服务端

    public static void main(String[] args) throws IOException {
    
                      /*
    
                       * 建立tcp服务端折思路
    
                       * 1,创建服务端socket服务,通过serverSocket对象
    
                       * 2,服务端必须提供一个端口,否则客户端无法连接
    
                       * 3, 获取连接过来的客户端对象
    
                       * 4,通过客户端对象获取 socket流读取客户端发来的数据
    
                       * 5.关闭资源,关客房端,关服务端
    
                       *
    
                       * */
    
                     
    
                      ServerSocket ss = new ServerSocket(20000);
    
                     
    
                      Socket s = ss.accept();
    
                      String ip = s.getInetAddress().getHostAddress();
    
                      InputStream in = s.getInputStream();
    
                      byte [] buf = new  byte [1024];
    
                      int len = in.read(buf);
    
                      String text =new String (buf,0,len);
    
                      System.out.println("server:"+text);
    
                     
    
                      System.out.println(ip);
    
                      s.close();
    
                      ss.close();
    
                     
    
                     
    
             }

    7 文本转换

    易错点:

    1,结束标记的原理

    2,当遇到上传过程中,会发生都在阻塞状态,

    文本转换-客户端

    public class TransClient {
    
     
    
             /**
    
              * @param args
    
              * @throws IOException
    
              * @throws 
    
              */
    
             public static void main(String[] args) throws IOException {
    
                      System.out.println("客户端运行......");
    
                      // 客户端:
    
                      // 步骤:
    
                      // 1,创建socket,明确地址和端口。
    
                      Socket s = new Socket("192.168.1.223", 10005);
    
     
    
                      // 2,源:键盘录入。获取需要转换的数据。
    
                      BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
    
                     
    
                      // 3,目的:网络,socket输出流。将录入的数据发送到服务端。
    
    //              OutputStream out = s.getOutputStream();
    
                      //既然都是字符数据,为了便于操作,使用额外功能,转换。同时提高效率。
    
                      //BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(out));可以使用打印流
    
                      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
                     
    
                      // 4,源:socket,socket读取流,读取服务端发回来的大写数据。
    
    //              InputStream in = s.getInputStream();
    
                      BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
    
                     
    
                      // 5,目的:客户端显示器,将大写数据显示出来。直接使用输出语句。
    
                     
    
                      // 6,频繁的读写操作。
    
                      String line = null;
    
                      while((line=bufr.readLine())!=null){
    
                             
    
                              //将读取键盘的数据发送到服务端。
    
                              out.println(line);
    
    //                       out.flush();
    
                              if("over".equals(line)){
    
                                       break;
    
                              }
    
                             
    
                              //读取服务端返回的数据。
    
                              String upperText = bufIn.readLine();
    
                              System.out.println(upperText);
    
                      }
    
                     
    
                      // 7,关闭资源。
    
                      s.close();
    
             }
    
     
    
    }

    文本转换-服务端

    public class TransServer {
    
     
    
             /**
    
              * @param args
    
              * @throws IOException
    
              */
    
             public static void main(String[] args) throws IOException {
    
     
    
                      System.out.println("服务端运行....");
    
                      // 服务端:
    
                      // 思路:
    
                      // 1,创建服务端socket 明确端口。
    
                      ServerSocket ss = new ServerSocket(10005);
    
                      while (true) {
    
                              // 获取客户端对象。
    
                              Socket s = ss.accept();
    
                              System.out.println(s.getInetAddress().getHostAddress()+".....connected");
    
     
    
                              // 2,源:socket输入流。读取客户端的发过来的数据。
    
                              BufferedReader bufIn = new BufferedReader(new InputStreamReader(
    
                                                s.getInputStream()));
    
     
    
                              // 3,目的:socket输出流。将转成大写的数据发送给客户端。
    
                              PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
     
    
                              // 4,频繁的读写操作。
    
                              String line = null;
    
                              while ((line = bufIn.readLine()) != null) {
    
                                       if("over".equals(line)){//如果客户端发过来的是over,转换结束。
    
                                                break;
    
                                       }
    
                                       System.out.println(line);
    
                                       // 将读取到的字母数据转成大写,发回给客户端。
    
                                       out.println(line.toUpperCase());
    
    //                                out.flush();
    
                              }
    
                              // 5,关闭客户端。
    
                              s.close();
    
                      }
    
     
    
             }
    
     
    
    }

    8 上传文件

    易错点:

    1结束标记的原理

    客户端

    public static void main(String[] args) throws UnknownHostException, IOException {
    
                      System.out.println("上传文件客户端运行......");
    
                      // 客户端:
    
                      // 步骤:
    
                      // 1,创建socket,明确地址和端口。
    
                      Socket s = new Socket("192.168.1.223", 10006);
    
     
    
                      // 2,源:读取文本文件。获取需要转换的数据。
    
                      BufferedReader bufr = new BufferedReader(new FileReader("tempfile\client.txt"));
    
                     
    
                      // 3,目的:网络,socket输出流。将录入的数据发送到服务端。
    
                      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
                     
    
                      // 4,频繁的读写操作。
    
                      String line = null;
    
                      while((line=bufr.readLine())!=null){
    
                             
    
                              out.println(line);
    
                             
    
                      }
    
                     
    
                      //给服务端发送一个结束标记。这个标记是约定标记。有点麻烦。可以更简单。使用socket对象的shutdownOutput();
    
    //              out.println("over");
    
                      s.shutdownOutput();//向服务端发送了结束标记。可以让服务端结束读取的动作。
    
                     
    
                     
    
                      // 5,源:socket,socket读取流,读取服务端发回来的上传成功信息。
    
                      BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
    
                      String info = bufIn.readLine();
    
                      System.out.println(info);
    
                     
    
                      // 6,关闭资源。
    
                      bufr.close();
    
                      s.close();
    
     
    
     
    
             }

    服务器端

    public static void main(String[] args) throws IOException {
    
     
    
     
    
                      System.out.println("上传文本服务端运行....");
    
                      // 服务端:
    
                      // 思路:
    
                      // 1,创建服务端socket 明确端口。
    
                      ServerSocket ss = new ServerSocket(10006);
    
                      while (true) {
    
                              // 获取客户端对象。
    
                              Socket s = ss.accept();
    
                              System.out.println(s.getInetAddress().getHostAddress()+".....connected");
    
     
    
                              // 2,源:socket输入流。读取客户端的发过来的数据。
    
                              BufferedReader bufIn = new BufferedReader(new InputStreamReader(
    
                                                s.getInputStream()));
    
     
    
                              // 3,目的:文件。
    
                              PrintWriter pw = new PrintWriter(new FileWriter("tempfile\server.txt"),true);
    
     
    
                              // 4,频繁的读写操作。
    
                              String line = null;
    
                              while ((line = bufIn.readLine()) != null) {
    
    //                                if("over".equals(line)){
    
    //                                        break;
    
    //                                }
    
                                       pw.println(line);
    
                              }
    
                             
    
                              // 5,发回给客户端上传成功字样。
    
                              PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
                              out.println("上传成功");
    
                             
    
                              // 6,关闭客户端。
    
                              s.close();
    
                      }
    
     
    
     
    
             }

    9 字符流不可以传输媒体文件

    有可能你在查表时不能查到,造成你你原来文件和转换后的不一样.

    比如下面图片里面的”1122”,查不到,那么表会给他一个默认的编码”1122”

     

    10 上传图片

    客户端

    上面图片要用到字节流
    
    public static void main(String[] args) throws IOException {
    
                      System.out.println("上传图片客户端运行......");
    
                      //1,创建socket。
    
                      Socket s = new Socket("192.168.1.223", 10007);
    
                     
    
                      //2,读取源图片。
    
                      File picFile = new File("tempfile\1.jpg");
    
                      FileInputStream fis = new FileInputStream(picFile);
    
                     
    
                      //3,目的是socket 输出流。
    
                      OutputStream out = s.getOutputStream();
    
                     
    
                      byte[] buf = new byte[1024];
    
                     
    
                      int len = 0;
    
                      while((len=fis.read(buf))!=-1){
    
                              out.write(buf,0,len);
    
                      }
    
                     
    
                      //告诉服务器端图片数据发送完毕,不要等着读了。
    
                      s.shutdownOutput();
    
                     
    
                      //读取上传成功字样。
    
                      InputStream in = s.getInputStream();
    
                      byte[] bufIn = new byte[1024];
    
                      int lenIn = in.read(bufIn);
    
                      System.out.println(new String(bufIn,0,lenIn));
    
                     
    
                     
    
                      //关闭。
    
                      fis.close();
    
                      s.close();
    
     
    
             }

    服务端

    String ip = s.getInetAddress().getHostAddress();
    
                              System.out.println(ip + ".....connected");
    
     
    
                              // 读取图片数据。
    
                              InputStream in = s.getInputStream();
    
     
    
                              // 写图片数据到文件。
    
                              File dir = new File("e:\uploadpic");
    
                              if (!dir.exists()) {
    
                                       dir.mkdir();
    
                              }
    
                              // 为了避免覆盖,通过给重名的文件进行编号。
    
                              int count = 1;
    
                              File picFile = new File(dir, ip + "(" + count + ").jpg");
    
                              while (picFile.exists()) {
    
                                       count++;
    
                                       picFile = new File(dir, ip + "(" + count + ").jpg");
    
                              }
    
                              FileOutputStream fos = new FileOutputStream(picFile);
    
     
    
                              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("上传成功".getBytes());
    
     
    
                              // 关闭资源。
    
                              fos.close();
    
                              s.close();

    解决重名覆盖问题

    // 为了避免覆盖,通过给重名的文件进行编号。
    
                              int count = 1;
    
                              File picFile = new File(dir, ip + "(" + count + ").jpg");
    
                              while (picFile.exists()) {
    
                                       count++;
    
                                       picFile = new File(dir, ip + "(" + count + ").jpg");
    
                              }

    解决并发问题

    public void run() {
    
     
    
                      try {
    
                              String ip = s.getInetAddress().getHostAddress();
    
                               System.out.println(ip + ".....connected");
    
     
    
                              // 读取图片数据。
    
                              InputStream in = s.getInputStream();
    
     
    
                              // 写图片数据到文件。
    
                              File dir = new File("e:\uploadpic");
    
                              if (!dir.exists()) {
    
                                       dir.mkdir();
    
                              }
    
                              // 为了避免覆盖,通过给重名的文件进行编号。
    
                              int count = 1;
    
                              File picFile = new File(dir, ip + "(" + count + ").jpg");
    
                              while (picFile.exists()) {
    
                                       count++;
    
                                       picFile = new File(dir, ip + "(" + count + ").jpg");
    
                              }
    
                              FileOutputStream fos = new FileOutputStream(picFile);
    
     
    
                              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("上传成功".getBytes());
    
     
    
                              // 关闭资源。
    
                              fos.close();
    
                              s.close();
    
                      } catch (IOException e) {
    
     
    
                      }
    
     
    
             }

    11 Http

    演示二:

             客户端:浏览器。

             服务端:自定义的服务端 myServer

             看到了如下信息:

    HTTP的请求消息:请求头+请求体,中间有空行。

            

    GET /myweb/1.html HTTP/1.1 // 请求行:请求方式   访问资源的路径  HTTP协议版本。

    Accept: application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*

    Accept-Language: zh-cn

    Accept-Encoding: gzip, deflate

    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)

    Host: 192.168.1.223:9090

    Connection: Keep-Alive

    空行

    请求体 

    演示三:模拟一个浏览器。

             客户端:自定义的浏览器。

             服务端:Tomcat

            

             发送和IE相同的HTTP协议的消息,收到了Tomcat服务器返回的数据。

            

    HTTP的应答消息:

    HTTP/1.1 200 OK  //应答行  http协议版本  应答状态码  应答描述信息

    Server: Apache-Coyote/1.1

    Accept-Ranges: bytes

    ETag: W/"467-1374891778953"

    Last-Modified: Sat, 27 Jul 2013 02:22:58 GMT

    Content-Type: text/html

    Content-Length: 467

    Date: Sun, 01 Sep 2013 07:26:09 GMT

    Connection: close

    空行

    应答体

    我自己定义的服务器

    public static void main(String[] args) throws IOException {
    
                     
    
                     
    
                      /*
    
                       *  自定义server 服务端
    
                       *  获取浏览器的信息。并反馈信息。
    
                       */
    
                      System.out.println("my server run....");
    
                      ServerSocket ss = new ServerSocket(9090);
    
                     
    
                      Socket s = ss.accept();
    
                      System.out.println(s.getInetAddress().getHostAddress()+"....connected");
    
                     
    
                      //读取客户端的数据。
    
                      InputStream in = s.getInputStream();
    
                      byte[] buf = new byte[1024];
    
                      int len = in.read(buf);
    
                      String text = new String(buf,0,len);
    
                      System.out.println(text);
    
                     
    
                      //给客户端回馈数据。
    
                      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
                      out.println("<font color='red' size='7'>欢迎光临</font>");
    
                     
    
                     
    
                      s.close();
    
                      ss.close();
    
                     
    
     
    
             }

     

     

    模拟客户端

    /*
    
                       * 模拟一个浏览器。发送之前IE发送的http消息。
    
                       */
    
                      Socket s = new Socket("192.168.1.223",8080);
    
                      //把IE的信息发送给服务端。
    
                      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
                      out.println("GET /myweb/3.html HTTP/1.1");
    
                      out.println("Accept: */*");
    
                      out.println("Host: 192.168.1.223:8080");
    
                      out.println("Connection: close");
    
                      out.println();//空行。
    
                     
    
                      //读取服务端的数据。
    
                      InputStream in = s.getInputStream();
    
                      byte[] buf = new byte[1024];
    
                      int len = in.read(buf);
    
                      String text = new String(buf,0,len);
    
                      System.out.println(text);
    
                     
    
                      s.close();

    12 URL对象

    Url常用方法和URLConnection

      

            */
    
             public static void main(String[] args) throws IOException {
    
                     
    
                      String str_url = "http://192.168.1.223:8080/myweb/2.html";
    
                     
    
                      //将url地址封装成对象。
    
                      URL url = new URL(str_url);
    
                     
    
    //              System.out.println("getProtocol:"+url.getProtocol());
    
    //              System.out.println("getHost:"+url.getHost());
    
    //              System.out.println("getPort:"+url.getPort());
    
    //              System.out.println("getPath:"+url.getPath());
    
    //              System.out.println("getFile:"+url.getFile());
    
    //              System.out.println("getQuery:"+url.getQuery());
    
                     
    
                      //获取指定资源的连接对象。//封装了socket。
    
                      URLConnection conn = url.openConnection();
    
                     
    
    //              System.out.println(conn);
    
                     
    
                      InputStream in = conn.getInputStream();
    
                      byte[] buf = new byte[1024];
    
                      int len = in.read(buf);
    
                      String text = new String(buf,0,len);
    
                      System.out.println(text);
    
                     
    
             }

     

    13 HTTP1.0和HTTP1.1区别

    HTTP1.0:一次连接一次请求。

    HTTP1.1:一次连接多次请求。

     

     

    14 常见的网络架构

             C/S: client / server 

                      特点:

                              1,程序员需要开发客户端和服务端。

                              2,维护较为麻烦。

                              3,将一部分运算转移到客户端来完成,减轻服务器端的压力。

                     

            

             B/S: browser / server

                      特点:

                              1,程序员只需要开发服务端。客户端使用系统已有的浏览器即可。

                              2,维护很简单。只需要维护服务端。

                              3,所有的运算的都在服务端。

                             

             目前流行BS

     

     


    作者:8亩田
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.

    本文如对您有帮助,还请多帮 【推荐】 下此文。
    如果喜欢我的文章,请关注我的公众号
    如果有疑问,请下面留言

    学而不思则罔 思而不学则殆
  • 相关阅读:
    docker-machine create ,,,
    docker run with zabbix3.0
    mysql 官网
    取模性质
    欧涛最短路【记录最短路径】
    P4568 飞行路线【分层图最短路】
    CCF201403 无线网络【限制型最短路】
    POJ2449 【第k短路/A*】
    Feeding Time 【bfs求最大连通块】
    printf特殊用法
  • 原文地址:https://www.cnblogs.com/liu-wang/p/8364687.html
Copyright © 2011-2022 走看看