黑马程序员——16Java网络编程1


------------ android培训 java培训 、期待与您交流!------------
 
1 ,网络模型
      OSI 参考模型7层:
            应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。
      TCP/IP 参考模型4层:
            应用层,传输层,网络层, 网络接口层。
黑马程序员——16Java网络编程1_第1张图片
网络通讯三要素: IP 地址,端口号,传输协议。
         import java.net.*;
             class IPDemo{
                     public static void main(String[] args)throws Exception{
                            //返回本地主机
                            InetAddress i=InetAddress.getLocalHost();
                            //将此 IP 地址转换为  String
                            System.out.println(i.toString());
                            //获取此 IP 地址的主机名
                            System.out.println("name:"+i.getHostName());
                            //返回 IP 地址字符串(以文本表现形式)。
                            System.out.println("address:"+i.getHostAddress());
                            //在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组
                            InetAddress[] ia=InetAddress.getAllByName("www.baidu.com");
                            for(InetAddress buf:ia) {
                                    System.out.println("name:"+buf.getHostName());
                                    System.out.println("address:"+buf.getHostAddress());
                            }
                    }
            }


2 UDP, 将数据以及源和目的封装成数据包,不需要建立连接。 每一个数据包 的大小限制在 64k 内。
      因无连接,是不可靠协议。 不需要建立连接,速度快。
    TCP, 建立连接,形成传输数据的通道。 在连接中进行大数据量传输。 通过三次握手完成连接,是可靠协议。 必须建立连接,效率会稍低。

3 Socket。网络编程实际就是Socket编程。Socket 就是为网络服务提供的一种机制, 通信两端都有 Socket, 网络通信其实就是 Socket 间的通信, 数据在两个 Socket 间通过 IO 传输。

4 UDP 传输。
          DatagramSocket DatagramPacket
          建立发送端和接收端。
          建立数据包。
          调用 Socket 的发送接收方法。
          关闭 Socket
          发送端与接收端是两个独立的运行程序。
 
需求:通过UDP传输方式,将一段文字数据发送出去。
import java.net.*;
class UdpSend{
        public static void main(String[] args)throws Exception {
                //1,创建udp服务。通过DatagramSocket对象。
                DatagramSocket ds=new DatagramSocket();
                //2,确定数据,并封装成数据包。
                byte[] buf="udp is my data".getBytes();
                DatagramPacket dp=
                        new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.6"),10000);
                //3,通过socket服务,将已有的数据包发送出去。通过send方法。
                ds.send(dp);
                //4,关闭资源。
                ds.close();
        }
}
需求:定义一个应用程序,用于接收udp协议传输的数据并处理的。
class UdpRece{
        public static void main(String[] args)throws Exception{
                //1,创建udp socket服务。建立端点。
                DatagramSocket ds=new DatagramSocket(10000);
                while(true){
                        //2,定义数据包,用于存储数据。
                        byte[] buf=new byte[1024];
                        DatagramPacket dp=new DatagramPacket(buf,buf.length);
                        //3,通过socket服务的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();
        }
}
 
5,UDP的一个小应用,聊天室。
         有收数据的部分,和发数据的部分,这两部分需要同时执行,那就需要用到多线程技术,一个线程控制收,一个线程控制发。因为收和发动作是不一致的,所以要定义两个run方法,而且这两个方法要封装到不同的类中。
        import java.net.*;
        import java.io.*;
        //发送端,多线程,实现Runnable接口 
        class Send implements Runnable{
                private DatagramSocket ds;
                public Send(DatagramSocket ds){
                         this.ds=ds;
                 }
                public void run(){
                        try{
                                BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
                                String line=null;
                                 while((line=bufr.readLine())!=null){
                                        //输入886,则结束。 
                                        if("886".equals(line))
                                                break;
                                         byte[] buf=line.getBytes();
                                        //把数据打包发送到指定IP地址和端口。 
                                        DatagramPacket dp=
                                    new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10002);
                                        ds.send(dp);
                                }
                                ds.close();
                        }
                        catch (Exception e){
                                throw new RuntimeException("发送端失败");
                        }
                }
        }
        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("接收端失败");
                          }
                 }
        }
        class ChatDemo{
                 public static void main(String[] args)throws Exception{
                        //发送端不用指定端口号,系统会自动将套接字绑定到本地可用的端口。 
                         DatagramSocket sendSocket=new DatagramSocket();
                        //接收端监听10002端口。 
                           DatagramSocket receSocket=new DatagramSocket(10002);
                         new Thread(new Send(sendSocket)).start();
                         new Thread(new Rece(receSocket)).start();
                }
        }

6 TCP 传输。
            Socket ServerSocket
            建立客户端和服务器端。
            建立连接后,通过 Socket 中的 IO  流进行数据的传输。
            关闭S ocket
          同样,客户端与服务器端是两个独立的应用程序。
     通过查阅socket对象,发现在该对象建立时,就可以去连接指定的主机。 因为tcp是面向连接的,所以在建立socket服务是时, 就要有服务端存在,并连接成功,形成通路后,在该通道进行数据传输。
              tcp传输的客户端和服务端的互访。
              import java.io.*;
             import java.net.*;
             class TcpClient{
           public static void main(String[] args)throws Exception{                
                              //1,建立socket服务,指定要连接主机和端口。 
                    Socket s=new Socket("192.168.1.7",10004);
                    //2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。 
                    OutputStream out=s.getOutputStream();
                    out.write("服务端,你好".getBytes());
                    //3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。 
                    InputStream in=s.getInputStream();
                    byte[] buf=new byte[1024];
                    int len=in.read(buf);
                    System.out.println(new String(buf,0,len));
                    //4,关闭客户端资源。 
                    s.close();
            }
    }
    class TcpServer{
            public static void main(String[] args)throws Exception {
                    //1,建立ServerSocket服务,监听本机10004端口。 
                    ServerSocket ss=new ServerSocket(10004);
                    //2,获取连接过来的客户端对象。 
                    Socket s=ss.accept();     //阻塞式方法。
                    //服务器显示连接的客户端ip地址。 
                    String ip=s.getInetAddress().getHostAddress();
                    System.out.println(ip+"...connected");
                    //3, 获取客户端发送过来的数据,那么要使用客户端对象的读取流方法,来读取数据。
                    InputStream in=s.getInputStream();
                    byte[] buf=new byte[1024];
                    int len=in.read(buf);
                    System.out.println(new String(buf,0,len));
                    //4,将服务器的数据写入客户端对象的输出流。 
                    OutputStream out=s.getOutputStream();
                    Thread.sleep(5000);    //线程休息5秒。
                    out.write("哥们收到,你也好".getBytes());
                    //5,关闭服务端,关闭客户端。 
                    s.close();
                    ss.close();
            }
    }
 
7,TCP传输的一个小应用,向服务器上传一个文本。   
        import java.io.*;
        import java.net.*;
        class TextClient{
        public static void main(String[] args)throws Exception{
                Socket s=new Socket("192.168.1.7",10006);
                BufferedReader bufr=new BufferedReader(new FileReader("IPDemo.java"));
                PrintWriter out=new PrintWriter(s.getOutputStream(),true);

                //第二种结束标记:时间戳,先发一个时间到服务器。
                 //DataOutputStream dos=new DataOutputStream(s.getOutputStream());
                 //long time=System.currentTimeMillis();
                 //dos.writeLong(time);
                String line=null;
                while((line=bufr.readLine())!=null){
                        out.println(line);
                }
                //第三种结束方案
                s.shutdownOutput();//关闭客户端输出流,相当于给流加入一个结束标记-1。

                //再向服务器发送原来的时间
                //dos.writeLong(time);

                //第一种结束标记:(自定义结束标记)out.println("over");
                BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
                String str=bufIn.readLine();
                System.out.println(str);
                bufr.close();
                s.close();
        }
}
class TextServer{
        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");

                //第二种结束标记,读取服务端发过来的时间。
                //DataInputStream dis=new DataInputStream(s.getInputStream());
                //long l=dis.readLong();

                BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
                PrintWriter out=new PrintWriter(new FileWriter("server.txt"),true);
                String line=null;
                while((line=bufIn.readLine())!=null) {
 

                        //第一种和第二种方案,判断客户端传来的标记,用来跳出循环。 
                        //if("over".equals(line))
                        // break;
                        out.println(line);
                }
                BufferedWriter bufOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                bufOut.write("上传成功");
                bufOut.newLine();
                bufOut.flush();
                out.close();
                s.close();
                ss.close();
        }
}

特别掌握结束的三种方案:
1,自定义结束标记 over,存在的问题:若文本中有一句over,就出错。来一个(@#¥%*&)作为结束标记, 则客户端应该先把标记发送给服务器。
2,时间戳。客户端现象服务器发送一个时间,结束后再把这个时间发送给服务器;服务端第一次接收到时间把它存起来,把第二次接收到时间和第一次接收的时间比较,用作服务器来结束判断。若客户端向服务器只发送一个基本数据,则用此方法最好。
tomcat服务器用的就是标记结束,结束标记符是一个空行符(上下文都有文本),用空行来分割各种协议字段(HTTP消息头字段,主体字段)。
3,标准的动作,API中Socket提供的 shutdownOutput()方法。


------------ android培训 java培训 、期待与您交流!------------

详情请查看: http://edu.csdn.net/heima  


你可能感兴趣的:(黑马程序员,黑马程序员,Java,网络编程,xuefei)