黑马程序员---java基础---7网路编程

 

 

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

网络编程;(net包)
 1.TCP  和  UDP   协议
 网络常用的协议有UDP和TCP/IP协议,那么着这两种传输协议到底有什么区别呢?
      1,首先UDP是将数据源和发送目标地址封装成数据包(通过类DatagramPacket来实现),不需要建立连接即可实现.
      2,再次UDP规定每次发送的数据包最大不能超过64k,如果源数据超过64k,则协议会自定将数据才分成若干小于64k的数据包依次发送.
      3,因为不需要连接即可传输数据,所以不能保证目标主机是否能接受到信息,是不安全的传输方式.
      4,正因为是不需要连接即可传输的,所以数据传输速度较快.
  就相当于去邮局寄东西,封装包(包有限制),明确对方的地址和端口,找不到人就丢掉数据。
    而TCP/IP协议恰好相反
      1,首先TCP/IP协议时需要两台主机建立连接后才能进行数据传输的,数据传输的特点是进行三步握手原则.
      2,传输过程中需要连接才可进行数据传输.一般是大数据传输,
      3,因为是建立在连接的基础上才能进行数据传输的,在传输前先进行三步握手确定连接成立才最后进行数据真正传输,所以传输速度会较慢
      4,也因为是连接后才进行数据传输,所以此传输方式是安全的可靠的.
   就相当于打电话, 确定对方存在,传输数据不需要封装,一步一步接收数据,安全的
 2.网络模型
  (a).按照OSI参考模型可将网络分成
   1,应用层
   2,表示层
   3,会话层
   4,传输层
   5,网络层
   6,数据连接层
   7,物理层
  (b).按照TCP/IP模型可将网络分成
   1,应用层
   2,传输层
   3,网际层
   4,主机至网络层
 3.IP地址
  InetAddress 一个没有构造方法的的类,直接被创建不需要被new对象。但他会抛出 IOException
  通过查API直接调用方法应用。

   InetAddress in = InetAddress.getByName("确定百度主机的IP地址。
   System.out.println("adress="+in.getHostAdress());//获取百度的IP地址字符串
   System.out.println("name="+in.getHostName());//获取百度的主机名
 4.Socket
  Socket是为网络服务的一个机制,
  网络的通信就是Socket通信,数据的 Socket 通信是通过IO传输的。
   (a).UDP的 Socket 通信
   DatagramSocket
   建立send的端,receive的端

    //客户端程序
   public class Send {
   public static void main(String[] ages) throws Exception{
    //创建一个客户端的套接字
    DatagramSocket ds=new DatagramSocket();
    String line;
    //获取用户在控制台输入的原数据
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    //循环如果有数据就想服务端发送
    while((line=br.readLine())!=null){
     //获取原数据的byte数组类型
     byte[] bt=line.getBytes();
     //将原数据的byte数组用DatagramPacket对象来打包
     DatagramPacket dp=new DatagramPacket(bt,bt.length,InetAddress.getByName("127.0.0.1"),10003);
     //将打包后的数据包发到服务端
     ds.send(dp);
     //判断如果用户输入 bay 结束客户端程序
     if(line.equals("over")){
   break;
     }
    }
    //关闭客户端程序
    ds.close();
   }
   }
   //服务端程序
   public class Receive {
   public static void main(String[] ages) throws Exception{
    //创建一个接收套接字
    DatagramSocket ds=new DatagramSocket(10003);
    while(true){
     //定义一个接受原数据的byte数组
     byte[] bt=new byte[1024];
     //创建一个用于才数据包的对象
     DatagramPacket dp=new DatagramPacket(bt,bt.length);
     //接受发送端发送过来的数据包放到创建好的数据包对象中
     ds.receive(dp);
     //将原数据从数据包中取出
     String line=new String(dp.getData(),0,dp.getLength());
     //大印数据
     System.out.println(line);
    } 
   }
   }


两个页面,一个发送端一个是接收端,从发送端发送数据,接收端接收 数据,
   send()和receive()都是阻塞式方法,也要放在while循环体内不断的进行发送和接收,但在发送端要定义标记结束发送数据,
   服务端是一直开着的要不断的接收数据,因为发送端不止一个要不断的对发送端发送过来的数据进行处理,所以一个服务端一般不进行关闭服务端操作。
 (b) UDP协议——聊天操作,发送端与服务端并存的操作。
   发送端与服务端并发进行数据的操作,并且进行了同步互斥,这就用到了多线程技术。两个页面,一个发送端一个是接收端,从发送端发送数据,接收端接收 数据,
   send()和receive()都是阻塞式方法,也要放在while循环体内不断的进行发送和接收,但在发送端要定义标记结束发送数据,
   服务端是一直开着的要不断的接收数据,因为发送端不止一个要不断的对发送端发送过来的数据进行处理,所以一个服务端一般不进行关闭服务端操作。
 (b) UDP协议——聊天操作,发送端与服务端并存的操作。
   发送端与服务端并发进行数据的操作,并且进行了同步互斥,这就用到了多线程技术。

import java.net.*;
   import java.io.*;

   class  dome20
   {
    public static void main(String[] args) throws Exception
    {
     DatagramSocket sendSocket= new DatagramSocket();
     DatagramSocket receSocket= new DatagramSocket(10000);
     send s= new send(sendSocket);
     rece r = new rece(receSocket);
     new Thread(s).start();
     new Thread(r).start();
    }
   }
   class send implements Runnable 
   {
    //数据进行UDP传输,一定要用到DatagramSocket
    private DatagramSocket  da;
    send(DatagramSocket da)
    {
     this.da=da;
    }
    public void run()
    {
     BufferedReader bufr= null;
     try
     {
      bufr = new BufferedReader(new InputStreamReader(System.in));
      String line= null;
      while ((line= bufr.readLine())!=null)
      {
       if("886".equals(line))
        break;
       byte [] by= line.getBytes();
       DatagramPacket dp= new DatagramPacket(by,by.length,InetAddress.getByName("192.168.1.255"),10000);
       da.send(dp);
      } 
     }
     catch (Exception e)
     {
      throw new RuntimeException("发送端发送失败");
     }
    }
   }
   class rece implements Runnable
   {
    private DatagramSocket da;
    rece(DatagramSocket da)
    {
     this.da=da;
    }
    public void run()
    {
     try
     {
      while (true)
      {
       byte[] by= new byte[1024];
       DatagramPacket dp = new DatagramPacket(by,by.length);
       da.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("接收端接收失败");
     }
    }
   }


(c)TCP数据传输,客户端和服务端, Socket 和  ServerSocket ,
  1.在建立Socket服务时就要有服务端存在,并连接成功,形成通路后在该通道进行数据的传输。(c)TCP数据传输,客户端和服务端, Socket 和  ServerSocket ,
  1.在建立Socket服务时就要有服务端存在,并连接成功,形成通路后在该通道进行数据的传输。

import java.net.*;
   import java.io.*;

   class  socket
   {
    public static void main(String[] args) throws Exception
    {
     //建立Socket服务,并指定其IP地址值,和端口
     Socket s= new Socket("221.11.42.212",10001);
     //为了发送数据,要获取Socket服务中的输出流对象。
     OutputStream out = s.getOutputStream();
     //字节输出流写入数据,
     out.write("w lai l ".getBytes());
     s.close();//关闭客户端

    }
   }
   class  server
   {
    public static void main(String[] args) throws Exception
    {
     //建立通道
     ServerSocket ss= new ServerSocket(10001);
     //通过accpet()方法来接收客户端对象
     Socket s= ss.accept();//accpet()是一个阻塞式方法
     String ip= s.getInetAddress().getHostAddress();
     System.out.println(ip+"...");
     //接收数据,通过获取字节流的输入流,
     InputStream in = s.getInputStream();
     byte[] by = new byte[1024];
     int len = in.read(by);
     System.out.println(new String(by,0,len));
     //服务端不关闭自己,但要关闭客户端,这样节约资源。
     s.close();
    }
   }
  2.建立一个文本转换服务器
   客户端把数据发送给服务端返回一个大小写互转的字符串,但客户端输入“over‘时结束客户端可以不停的进行输入字符串操作。
   
   class  socket
   {
    public static void main(String[] args) throws Exception
    {
     //建立Socket服务,并指定其IP地址值,和端口
     Socket s= new Socket("123.138.88.232",10001);
     //定义键盘录入的流对象。
     BufferedReader bufr= 
      new BufferedReader(new InputStreamReader(System.in));

     //定义目的,将数据写入socket服务,发送给服务端。
     //BufferedWriter bufw=
      //new BufferedWriter (new OutputStreamWriter( s.getOutputStream()) );
     //打印输入流
     PrintWriter pw = new PrintWriter(s.getOutputStream(),true);

     //定义一个Socket读取流,读取服务端返回信息。
     BufferedReader buf= 
      new BufferedReader(new InputStreamReader(s.getInputStream()));

     String line= null;
     while ((line= bufr.readLine())!=null)
     {
      if ("over".equals(line))
       break;
      //bufw.write(line);//数据只写入的缓冲区中需要刷新才可以
      //bufw.newLine();//读取数据用到的是readLine()方法他是一个阻塞式方法,需要靠回车符(也就是换行符)来判断数据是否到结尾。
      //bufw.flush();
      pw.println(line);//自动刷新,自带换行。
      //发送给服务端一段数据,接收一下服务端返回的数据
      String str = buf.readLine();
      System.out.println("server::"+str);
     }
     
     bufr.close();//关闭键盘录入
     
     s.close();//关闭客户端

    }
   }
   class  server
   {
    public static void main(String[] args) throws Exception
    {
     //建立通道
     ServerSocket ss= new ServerSocket(10001);
     //通过accpet()方法来接收客户端对象
     Socket s= ss.accept();//accpet()是一个阻塞式方法
     String ip= s.getInetAddress().getHostAddress();
     System.out.println(ip+"...");
     //接收数据,通过获取字节流的输入流,
     BufferedReader bufwr=
      new BufferedReader (new InputStreamReader(s.getInputStream()) ) ;
     //定义一个字节输入流给客户端返回服务端的信息。
     //BufferedWriter bufrw=
      //new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

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

     String line = null;
     while ((line= bufwr.readLine())!=null)
     {
      System.out.println(line);//打印客户端的数据。
      //bufrw.write(typeChange(line));
      //bufrw.newLine();
      //bufrw.flush();//结束标记,不然一直等。
      pw.println(typeChange(line));
     }
     ss.close();
     s.close();
    }
    public static String typeChange(String str)
     
    {
          
     char[] ch = str.toCharArray();//把接收的字符串转成字符数组
        
     for (int i = 0; i < ch.length; i++)//遍历字符数组
     {
       if(ch[i]>=97 && ch[i]<=122)//判断字符数组是否为小写
       {
         String s = String.valueOf(ch[i]);  
         s=s.toUpperCase();//把小写转成大写
         char c=s.charAt(0);
         ch[i] = c;               //替换大小写
       }
      else
       {  
          String s = String.valueOf(ch[i]);
          s=s.toLowerCase();         //把大写转成小写
          char c=s.charAt(0);
          ch[i] = c;     //替换大小写
        }
     }
          
      String arr= String.valueOf(ch);   //数组转换成字符串的形式
        return arr;
      }
   }
   /*
   从中我发现,客户端和服务端会出现莫名的等待,为什么会出现这样的情况,因为在客户端和服务端都有阻塞式方法,没有读到结束标记就要一直等,导致两端都在等待

   对于这样必须给阻塞式方法加上结束标记,
   */
   /*
   还有一种情况就是要定义结束标记,用到了shutdownOutput()//关闭客户短的输出流,相当于给流中加入一个结束标记-1;shutdownInput()
   */
   tcp并发执行
   多个客户端并发访问服务端,就用到了多线程技术,服务端把每个客户端封装的每一个单独的线程里,服务端就可以并发同时执行多个客户端,
   把并发执行代码封装在多线程内。

    class pic implements Runnable
    {
     private Socket s;
     pic (Socket s)
     {
      this.s = s;
     }
     public void run()
     {
      String ip= s.getInetAddress().getHostAddress();
      int counnt= 1;//不可定义在成员位置上,因为会造成多条线程共享这个数据。
          //不能直接counnt++因为会造成有点文件文件已经存在被覆盖。
      try
      {
      
      System.out.println(ip+"...");
       //但在复制文件时会出现相同文件名文件,这样如何区分呢,在这里相同名称就会覆盖文件。
         //可以定义变量来在文件名上来区分,
      
      File f= new File(ip+"("+(counnt)+")"+".jpg");//自定义文件
      //但在定以变量名称的时counnt++,但文件名存在还是会覆盖,所以要继续进行判断。
      while (f.exists())//判断不止一次,要不断循环进行判断。所以while循环
      {
       f= new File(ip+"("+(counnt++)+")"+".jpg");
      }
      
      FileOutputStream file = new FileOutputStream(f);//多线程并发访问,
      InputStream in= s.getInputStream();
      byte[] by= new byte[1024];
      int len = 0;
      while ((len= in.read(by))!=-1)
      {
       file.write(by,0,len);
      }

      OutputStream out = s.getOutputStream();
      out.write("上传成功".getBytes());
      file.close();
      s.close();
      }
      catch (Exception e)
      {
       throw new RuntimeException("客户端访问失败");
      }
     }
    }
    class  socket
    {
     public static void main(String[] args) throws Exception
     {
      if (args.length!=1)
      {
       System.out.println("请传入一个正确的文件");
       return;
      }

      File files= new File(args[0]);

      if (!(files.exists()&&files.isFile()))
      {
       System.out.println("上传的文件不存在或文件不是一个文件");
       return;
      }
      if (!(files.getName().endsWith(".jpg")))
      {
       System.out.println("上传文件不是以。jpg 的图片文件");
       return;
      }
      if (files.length()>1024*1024*5)
      {
       System.out.println("上传的文件过大");
       return;
      }
      //建立Socket服务,并指定其IP地址值,和端口
      Socket s= new Socket("123.138.88.232",10002);
      
      FileInputStream file= new FileInputStream(files);//发送的文件是待定的。
      //获取输出流
      OutputStream out = s.getOutputStream();
      byte[] by = new byte[1024];
      int len = 0;
      while ((len= file.read(by))!=-1)
      {
       out.write(by,0,len);
      }
      s.shutdownOutput();//告诉服务端,我结束了
      
      //接收服务端的返回数据
      InputStream in = s.getInputStream();
      byte[] buf= new byte[1024];
      int length = in.read(buf);
      String str= new String(buf,0,length);
      System.out.println("server::"+str);
      
      file.close();
      s.close();//关闭客户端

     }
    }
    class  server
    {
     public static void main(String[] args) throws Exception
     {
      //建立通道
      ServerSocket ss= new ServerSocket(10002);
      while (true)
      {
       Socket s= ss.accept();//accpet()是一个阻塞式方法
       new Thread(new pic(s)).start();
       new Thread(new pic(s)).start();

      }
     }
    }


服务端可以多客户端并发访问也可以服务端对于单个客户端限制访问次数。
    例如限制客户端登陆服务器,超过三次中断登陆。在这里只要对登陆的次数定义标记,以便确定登陆,遍历文件,要定义标记。
  5.自定义服务端,自定义客户端,tomcat服务器。
   1.客户端:浏览器(telnet) 服务端:自定义。2.客户端;自定义  服务端:Tomcat服务器
   3.客户端:自定义   服务端:Tomcat服务器。
  6.URL 对象。操作字符串对象。内部也封装了Socket对象。
    String getFile()
       获取此 URL 的文件名。
    String getHost()
       获取此 URL 的主机名(如果适用)。
    String getPath()
       获取此 URL 的路径部分。
    int getPort()
       获取此 URL 的端口号。
    String getProtocol()
       获取此 URL 的协议名称。
    String getQuery()
       获取此 URL 的查询部分。
   重要:URLConnect类
    URLConnection openConnection()
       返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
    URLConnection openConnection(Proxy proxy)
       与 openConnection() 类似,所不同是连接通过指定的代理建立;不支持代理方式的协议处理程序将忽略该代理参数并建立正常的连接。
   在Java.net包中定义了URLConnection类,该类用来表示与URL建立的通信连接。URLConnection类的实例通过调用URL类的openConnection()方法获得。URLConnection类用于访问网络资源的主要方法如下所示:
           Void addRequestProperty(String key,String value):添加由键值对指定的一般请求属性。
           Abstract void connect():打开到此URL引用的资源的通信链接(如果尚未建立这样的连接)。
           ObjectgetConnect():检索此URL连接的内容。
           Long getDate():返回date头字段的值。
           Boolean getDefaultUseCaches():返回URLConnection的useCaches标志的默认值。
           InputStream getInputStream():返回从此打开的连接读取的输入流。
           OutputStream getOutputStream():返回写入到此连接的输出流。
           URL getURL():字段的值。
           Boolean getUseCaches():返回此URLConnection的useCaches字段的值。服务端可以多客户端并发访问也可以服务端对于单个客户端限制访问次数。
    例如限制客户端登陆服务器,超过三次中断登陆。在这里只要对登陆的次数定义标记,以便确定登陆,遍历文件,要定义标记。
  5.自定义服务端,自定义客户端,tomcat服务器。
   1.客户端:浏览器(telnet) 服务端:自定义。2.客户端;自定义  服务端:Tomcat服务器
   3.客户端:自定义   服务端:Tomcat服务器。
  6.URL 对象。操作字符串对象。内部也封装了Socket对象。
    String getFile()
       获取此 URL 的文件名。
    String getHost()
       获取此 URL 的主机名(如果适用)。
    String getPath()
       获取此 URL 的路径部分。
    int getPort()
       获取此 URL 的端口号。
    String getProtocol()
       获取此 URL 的协议名称。
    String getQuery()
       获取此 URL 的查询部分。
   重要:URLConnect类
    URLConnection openConnection()
       返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
    URLConnection openConnection(Proxy proxy)
       与 openConnection() 类似,所不同是连接通过指定的代理建立;不支持代理方式的协议处理程序将忽略该代理参数并建立正常的连接。
   在Java.net包中定义了URLConnection类,该类用来表示与URL建立的通信连接。URLConnection类的实例通过调用URL类的openConnection()方法获得。URLConnection类用于访问网络资源的主要方法如下所示:
           Void addRequestProperty(String key,String value):添加由键值对指定的一般请求属性。
           Abstract void connect():打开到此URL引用的资源的通信链接(如果尚未建立这样的连接)。
           ObjectgetConnect():检索此URL连接的内容。
           Long getDate():返回date头字段的值。
           Boolean getDefaultUseCaches():返回URLConnection的useCaches标志的默认值。
           InputStream getInputStream():返回从此打开的连接读取的输入流。
           OutputStream getOutputStream():返回写入到此连接的输出流。
           URL getURL():字段的值。
           Boolean getUseCaches():返回此URLConnection的useCaches字段的值。

class  URLConnectionDome
    {
     public static void main(String[] args) throws Exception
     {
      URL url= new URL("http://192.168.1.212:8080/mywed/dome.html")
      URLConnection conn= url.openConnection();
      System.out.println(conn);
       //封装了Socket对象
      InputStream in= conn.getInputStream();
      byte[] buf= new byte[1024];
      int len = in.read(buf);
      System.out.println(new String(buf,0,len));

     }
    }


 


---------------------- <a href="

http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值