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

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

    学而不思则罔 思而不学则殆
  • 相关阅读:
    hdu 5723 Abandoned country 最小生成树 期望
    OpenJ_POJ C16G Challenge Your Template 迪杰斯特拉
    OpenJ_POJ C16D Extracurricular Sports 打表找规律
    OpenJ_POJ C16B Robot Game 打表找规律
    CCCC 成都信息工程大学游记
    UVALive 6893 The Big Painting hash
    UVALive 6889 City Park 并查集
    UVALive 6888 Ricochet Robots bfs
    UVALive 6886 Golf Bot FFT
    UVALive 6885 Flowery Trails 最短路
  • 原文地址:https://www.cnblogs.com/liu-wang/p/8364687.html
Copyright © 2011-2022 走看看