• 网络编程


    一、网络模型

    OSI(Open System Interconnection开放系统互连)参考模型

    1.物理层——这一层的数据叫比特

    2.数据链路层——这一层的数据叫帧(对数据进行MAC地址,即网卡的地址进行封装与解封装)

    3.网络层——对数据进行IP地址的封装与解封装,这一层数据叫数据包

    4.传输层——这一层数据叫段,定义了一些传输数据的协议和端口号,对从下层传来的数据进行分段和传输

    5.会话层——主要在你的系统之间发起会话或者接受会话请求

    6.表示层——主要是进行对接收的数据进行解释、加密或解密、压缩与解压缩等。

    7.应用层——主要是一些终端的应用。

    二、网络通讯要素

    1.IP地址

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

    2.端口号

    有效端口:0-65535   其中0-1024系统使用或保留端口。

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

    3.传输协议

    常见协议:TCP、UDP

    (1)UDP

    不需要建立连接,每个数据报的大小限制在64K内,因为无连接,是不可靠协议,但是速度快。

    (2)TCP

    需建立连接,可进行大数据量传输,通过三次握手完成连接,是可靠协议,效率低。

     在java中,网络编程的包为java.net包,在INetAddress接口中封装IP地址,有两个子类INet4Address和INet6Address。

    例1:

    public static void oper() throws UnknownHostException
    {
         //获取取本地主机ip地址对象
         InetAddress ip=InetAddress.getLocalHost();
         System.out.println(ip.getHostAddress());
         System.out.println(ip.getHostName());
        //如何获取指定的主机的ip地址对象
        ip=InetAddress.getByName("my_think"); //InetAddress.getByName("192.168.1.100);也可以
    }

    三、Socket

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

    DatagramSocket此类表示用来发送和接收数据报包的套接字。

    DatagramPacket此类表示数据报包。

    例2:UDP实例

    //发送端
    public static void main(String[] args)  throws SocketException
    {
         /*
          *创建UDP传输的发送端思路:
          *1. 建立udp的socket服务
          *2. 将要发送的数据封装到数据包中
          *3. 通过udp的socket服务将数据包发送出去
          *4. 关闭socket服务
        */
        DatagramSocket ds=new DatagramSocket();
        // String str="UDP传输演示:哥们来了!";
    BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
    String line=null;
    while ((line=bufr.readLine())!=null)
    {
    if ("over".equals(line))
    break;
    byte[] buf=line.getBytes();
    DatagramPacket dp=new Datagrampacket(buf,buf.length,InetAddress.getName("192.168.1.100",10000);
    // byte[] buf=str.getBytes(); // DatagramPacket dp=new Datagrampacket(buf,buf.length,InetAddress.getName("192.168.1.100",10000); ds.send(dp);
        ds.close();
    }
    
    //接收端
    public static void main(String[] args)
    {
         /*
          *建立UDP接收端的思路
          *1. 建立udp socket服务
          *2. 创建数据包,用于存储接收到的数据,方便用数据包对象的方法解析这些数据
          *3. 使用socket服务的rece方法将接收到的数据存储到数据包中。
          *4. 通过数据包的方未能解析数据包中的数据
          *5. 关闭资源
         */
         DatagramSocket ds=new DatagramSocket(10000);
    while(true)
    {
    byte[] buf=new byte[1024]; DatagramPacket dp=new DatagramPacket(buf,buf.legnth); ds.receive(dp); //阻塞式的 String ip=dp.getAddress().getHostAddress(); int port=dp.getPort(); String text=new String(dp.getdata(),0,dp.getLength()); }
    ds.close();
    }

     例3:TCP传输

    Socket和ServerSocket ,这一点和UDP不一样,UDP中DatagramSocket即可接收也可发送。

    建立客户端和服务器端

    建立连接后,通过Socket中的IO流进行数据的传输

    最后需要关闭socket

    //TCP客户端
    public static void TCPClientDemo throws UnKnowHostException,IOException
    {
         /*客户端发数据到服务端
          *Tcp传输,客户端建立的过程
          *1. 创建tcp客户端socket服务,使用的是Socket对象,建议该对象一创建就明确目的地,要连接的主机。
          *2. 如果连接建立成功,说明数据传输通道已建立。该通道就是socket流,是底层建立好的。既然是流,说明这里既有输入,又有输出。想要输入或者输出流对象,可以找socket来获取。
         *可以通过getOutputStream()和getInputStream()来获取两个字节流。
         *3. 使用输出流,将数据写出。
         *4. 关闭资源,其实质是断开连接
         */
         Socket socket=new Socket("192.168.1.100",10002);
         OutputStream out=socket.getOutputStream();
         out.write("tcp演示!");
    //读取服务端返回的数据
    InputStream in=socket.getInputStream();
    byte[] buf=new byte[1024];
    int len=in.read(buf);
    string text=new String(buf,0,len);
    system.out.println(text); socket.close(); }
    //TCP服务端 public static void main(String[] args) { /* *建立tcp服务端的思路 *1. 创建服务端socket服务,通过ServerSocket对象 *2. 服务端必须对外提供一个端口,否则客户端无法连接 *3. 获取连接过来的客户端对象 *4. 通过客户端获取socket流读取客户端发来的数据,并打印在控制台上 *5. 关闭资源,需要关客户端和服务端 */ ServerSocket ss=ServerSocket(10002); 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(ip+":"+text);
    //使用客户端socket对象的输出流给客端返回数据
    OutputStream out=s.getOutputStream();
    out.write("收到"); s.close(); ss.close(); }

     在上传文件时,为了告诉服务器,客户端写完了。可添加:

    socket.shutdownOutput();

     服务器端因为accept阻塞,所以在一个客户处理完成之前,其他客户必须等待。可以用多线程解决:

    public static void main(String [] args) throws IOException
    {
         ServerSocket ss=new ServerSocket(10006);
         while(true)
         {
               Socket s=ss.accept();
               //以下多线程执行
               new Thread(new UploadTask(s)).start();
         }
    }
    
    
    //创建UploadTaskod类
    public class UploadTask implements Runnable
    {
        private Socket s;
        public UploadTask(Socket s){
            this.s=s;
        }
        @override
        public void run()
        {
             String ip=s.getInetAddress().getHostAddress();
             System.out.println(ip+"....connected");
             try{
                  InputStream in=s.getInputStream();
                  File dir=new File("c:\pic");
                  if (!dir.exist()){
                      dir.mkdirs();
                  }
                   File file=new File(dir,ip+".bmp");
                  FileOutputStream fos=new fileOutputStream(file);
                   byte[] buf=new byte[1024];
                  int len=0;
                  while(l(len=in.read(buf))!=-1){
                      fos.write(buf,0,len);
                  }
                   OutputStream out=s.getOutputStream();
                   out.write("上传成功!",getBytes());
                   fos.close();
                   s.close();
           }
           catch(Exception e)
           {
     
           }
        }
    }

    例:自定义www服务器

    public static void main(String[] args) throws IOException
    {
        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(); }

     例:模拟浏览器

    public class MyBrowser{
        public static void main(String[] args) throws UnknownHostException,IOException
        {
             Socket s=new Socket("192.168.1.100",8080);
             //模拟浏览器,给tomcat发送符合http协议的请求消息
             PrintWriter out=new printWriter(s.getOutputStream(),true);
             out.println("GET /myweb/1.html HTTP/1.1");
             out.println("Accept: */*");
             out.println("Host:192.168.1.100:8080");
             out.println("Connection:close");
             out.printlnl();
             
    
             InputStream in=s.getInputStream();
             byte[] buf=n ew byte[1024];
             int len=in.read(buf);
             String str=new String(buf,0,len);
             System.out.println(str);
             s.close();
    
        }
    
    }

    例:URL例

    public static void main(String[] args) throws NalformedURLException
    {
        String str_url="http://192.168.1.100:8080/myhweb/1.html?name=lisi"
        URL url=new URL(str_url);
        System.out.println(url.getProtocal()); 
        System.out.println(urlgetHost());
        System.out.println(url.getPort());
        System.out.println(url.getFile());
        System.out.println(url.getPath());
        System.out.println(url.getQuery());
        //URL的openStream()方法可以打开此地址的Socket流,并返回此连接的输入流,可用以下方法方法模拟浏览器
        InputStream in=url.openStream();
        byte[] buf=new byte[1024];
        int len=in.read(buf);
        String text=new String(buf,0,len);
        System.out.println(text);
        in.close();
        
    }

    使用URL对象的openConnection()方法可便的获得输入输出流。

    URLConnection conn=url.openConnection();
    InputStream in=conn.getInputStream(); //此方法非常简捷
    byte[] buf=new byte[1024];
    int len=in.read(buf);
    String text=new String(buf,0,len);
    Sytem.out.print(text);
  • 相关阅读:
    MySQL主从复制故障1595报错【原创】
    深入理解计算机系统(3.1)------汇编语言和机器语言
    深入理解计算机系统(2.7)------浮点数舍入以及运算
    深入理解计算机系统(2.7)------二进制小数和IEEE浮点标准
    深入理解计算机系统(2.6)------整数的运算
    深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字
    深入理解计算机系统(2.4)------整数的表示(无符号编码和补码编码)
    Spring详解(七)------AOP 注解
    深入理解计算机系统(2.3)------布尔代数以及C语言运算符
    深入理解计算机系统(2.2)------进制间的转换原理
  • 原文地址:https://www.cnblogs.com/jsddj/p/7721777.html
Copyright © 2020-2023  润新知