JAVA网络变成学习第一部分

Java网络编程

网络通信的要素

  • 对方的IP地址

  • 对应的端口号

192.168.16,124:5900

TCP/IP参考模型

分为四层,应用层,传输层,网络层,数据链路层(包含链路层和物理层)

得到对应域名的IP地址,可以在cmd中使用ping命令+域名

JAVA网络变成学习第一部分

小结:

  1. 网络编程上的主要问题

    • 准确定位到网络上的一台或者多台主机

    • 找到主机之后如何进行数据通信

  2. 网络编程中的要素

    • IP和端口号

    • 网络通信协议

  3. Java中万物皆对象,有这些要素一定有对应的类

 

 

IP

IP地址:InetAddress

可以在cmd用ipconfig指令查询相关数据,但是我们能看到的都是局域网IP,只是这个局域网可能比较大(小区),如果公网IP被查到就会遭受入侵

  • 唯一定位一台网路上的计算机

  • 127.0.0.1是本机IP(localhost),没有网也可以ping通过这个IP

  • IP地址的分类

    • IPV4/IPV6

      • IPV4 127.0.01 ,4个字节组成,每个字节是0-255(2^8),大概有42亿个(2^32),国际不够用,国际分配不均(这些指公网),IPV4私网还够用

      • IPV6 128位,8个无符号整数,十六进制,所以有abcde,这个是用不完的(16^32)

        2001:0bb2:aaaa:0015:0000:0000:1aaaa:1312

         

    • 公网-私网

用到一个网络类InetAddress

package Internet_Stu;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class TestInterAddress {
   public static void main(String[] args) {
       try {

           //查询本机地址的三种方式
  InetAddress inet1=InetAddress. getByName("127.0.0.1") ; //127.0.0.1代表本机地址
           System.out.println(inet1);

  InetAddress inet2=InetAddress. getByName("localhost") ; //localhost代表本地主机
           System.out.println(inet2);

           InetAddress inet3=InetAddress.getLocalHost();
           System.out.println(inet3);
           
           //通过域名查询网站IP地址
InetAddress inet4=InetAddress. getByName("www.baidu.com") ;
           System.out.println(inet4);

           //inet4已经与百度的IP绑定
           System.out.println(inet4.getAddress()); //返回一组地址,这个一般没什么用
           System.out.println(inet4.getCanonicalHostName());   //规范名
           
           System.out.println(inet4.getHostAddress());             //主机地址
           
           System.out.println(inet4.getHostName());                //得到对应主机的域名

      } catch (UnknownHostException e) {
           e.printStackTrace();
      }

  }
}

JAVA网络变成学习第一部分

 

端口

端口表示计算机上的一个程序的进程

  • 不同的进程有不同的端口号,用来区分软件

  • 被规定0--65535,TCP和UDP协议的端口号不冲突,也就是都有0--65535

  • 端口分类

    • 公有端口0~1023

    • 程序注册端口:1024~49151,分给用户和程序

      • Tomcat:8080

      • MySQL:3306

    • 动态,私有端口49152~65535,尽量不要用这里面的端口

      //相关控制台命令
      netsat -ano //查看所有端口
      netsat -ano|findstr "5900" //查看指定端口号  
      tasklist|findstr "20496"
        //linux中,| 表示管道,过滤的意思

      JAVA网络变成学习第一部分

通信协议

网络通信协议包括:速率,传输码率,代码结构,传输控制

由于问题非常复杂,所以需要分层

TCP/IP协议簇

其中比较重要的两个:

  • TCP:用户传输协议

  • UDP:用户数据报协议

出名的协议

  • TCP

  • IP:网络互联协议(属于网络层)

TCP UDP对比

  • TCP 打电话

    • 连接,稳定

    • 三次握手,四次挥手

    • 分为客户端,服务端(C/S)

    • 传输完成,释放连接,效率低

  • UDP 发短信

    • 不连接,不稳定

    • 客户端服务端没有明确界限

    • 不管有没有准备好,都可以发给你

    • DDOS:洪水攻击,使用的就是UDP,饱和攻击

TCP实现聊天

package com.he.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务器端代码
public class TcpServer {
  {
       try {
           //1,开启一个地址,localhost 9999
           ServerSocket server = new ServerSocket(9999);

           //2,等待客户端链接过来,通过服务器socket的accept方法得到客户端的socket对象
           Socket socket=server.accept();

           /*3,读取客户端的消息,因为在客户端,
            socket这个对象已经通过getOutputStream读取过输入信息了
            所以可以直接拿出来*/
           InputStream is=socket.getInputStream();
           
           //创建一个管道流
           ByteArrayOutputStream baos=new ByteArrayOutputStream();
           byte[] buffer=new byte[1024];
           int len;
           //所有字节都读进对象里,返回byte数量,如果溢出就返回-1
           while((len=is.read(buffer))!=-1){
               baos.write(buffer,0,len);//offset就是开始位置和终止位置
               
          }
           System.out.println(baos.toString());

      } catch (IOException e) {
           e.printStackTrace();
      }
  }
}



package com.he.net;

import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

//客户端代码
public class TcpClient {
   public static void main(String[] args) {
       try {
             //1,得到服务器的地址
          InetAddress serverIP= InetAddress.getByName("127.0.0.1");
         //2,得到端口号
           int port=9999;
            //3,为该IP,端口号创建一个Socket连接
           Socket socket=new Socket(serverIP,port);
           //4,发送消息IO流
           OutputStream outputStream = socket.getOutputStream();
           outputStream.write("第一次网络变成学习".getBytes());
      } catch (Exception e) {
           e.printStackTrace();
      }
  }

}
//这两段代码都有在finally处理IO流的资源释放问题,同时注意作用域问题,在finally识别不到try语句块中定义的对象

Tips: 创建绑定端口的服务器进程后, 当客户进程的 Socket构造方法返回成功, 表示客户进程的连接请求被加入到服务器进程的请求连接队列中. 虽然客户端成功返回 Socket对象, 但是还没跟服务器进程形成一条通信线路. 必须在服务器进程通过 ServerSocket 的 accept() 方法从请求连接队列中取出连接请求, 并返回一个Socket 对象后, 服务器进程这个Socket 对象才与客户端的 Socket 对象形成一条通信线路.(转自CSDN《Java网络编程精解》)

  • 客户端创建了对应服务器IP和端口号的socket,就向服务器发送了一条连接请求

  • 服务器端调用ServerSocket的accept()方法,就从请求队列里取出一条连接请求

  • 创建ServerSocket的时候可以输入一个请求队列最大长度,如果溢出就弹出错误

  • 关于IO流到底用I还是用O

    • 首先要声明的是,输入输出都是站在程序所在内存划分的

    • 输入流(input)是从其读取数据,输出流是向其写数据(output)

    • 从磁盘读数据是输入流,server从client的socket里读数据也是用输入流

    • 把内存里的数据写到控制台是输出流,把控制台上键盘输入的数字读到内存中是输入流

//服务器代码
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpService {
   public static void main(String[] args) {

           ByteArrayOutputStream baos=null;
           InputStream is=null;
           Socket socket=null;
           ServerSocket server=null;
           try {
               //服务器做的任务是接收数据并打印
               //1,为服务器进程申请一个端口号
               server = new ServerSocket(9999);
               //2,从消息队列中取出消息,不能直接取,要通过返回一个Socket对象取数据
               socket = server.accept();
               //3,从该Socket对象中读取数据,从数据流中取数据,所以是用InputStream对象接收
                is = socket.getInputStream();
               //使用管道流
                baos = new ByteArrayOutputStream();
               byte[] buffer = new byte[1024];
               int len;
               //从InputStream对象里接收数据
               while ((len = is.read(buffer)) != -1)//取长度
              {
                   //数据写进管道类对象里
                   baos.write(buffer, 0, len);
              }
               System.out.println(baos.toString());


          } catch (IOException e) {
               e.printStackTrace();
          }finally {
               //关闭资源,提升作用域
               if(baos!=null){
               try {
                   baos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
              }
               if(socket!=null) {
                   try {
                       socket.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
              }
               if(server!=null) {
                   try {
                       server.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
              }
               if(is!=null) {
                   try {
                       is.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
              }
          }

  }
}

//客户端代码
package TcpByMyself;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpClient {

   public static void main(String[] args) {
       OutputStream os=null;
       Socket socket=null;
       try {
           //客户端要做的事情是将一个含内容的socket对象发送给服务器端
           //1,得到服务器IP地址(总得确定要传送给哪个服务器)
           InetAddress inet;
           inet = InetAddress.getByName("127.0.0.1");
           //2,进一步得到端口号
           int port=9999;
           //3,创建一个socket对象,这个socket对应着服务器端对应进程的那个socket
           socket=new Socket(inet,port);
           //4,用IO流对象与socker类对象绑定,socket类有一个getOutputStream()的方法
           os=socket.getOutputStream();
           //5,往io流对象里写内容,write需要的是Byte[],需要用getByte()将String转换成Byte数组
           os.write("第一次学习网络编程".getBytes());

      } catch (UnknownHostException e) {
           e.printStackTrace();
      } catch (IOException e) {
           e.printStackTrace();
      }finally {
           //释放IO流对象的资源
           if(os!=null)
          {
               try {
                   os.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(socket!=null)
          {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }


}

这里在finally不写close()部分是不能运行通过的

 

上一篇:网络编程——IP


下一篇:网络编程啊