网络编程

IP和端口号

InetAdress类

InetAddress类没有提供公共的构造器,而是提供了如下几个静态方法来获取
InetAddress实例
public static InetAddress getLocalHost()
public static InetAddress getByName(String host)
InetAddress提供了如下几个常用的方法
public String getHostAddress():返回 IP 地址字符串(以文本表现形式)。
public String getHostName():获取此 IP 地址的主机名
public boolean isReachable(int timeout):测试是否可以达到该地址

 * 一、网络编程中有两个主要的问题:
 * 1.如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
 * 2.找到主机后如何可靠高效地进行数据传输
 *
 * 二、网络编程中的两个要素:
 * 1.对应问题一:IP和端口号
 * 2.对应问题二:提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)
 *
 *
 * 三、通信要素一:IP和端口号
 *
 * 1. IP:唯一的标识 Internet 上的计算机(通信实体)
 * 2. 在Java中使用InetAddress类代表IP
 * 3. IP分类:IPv4 和 IPv6 ; 万维网 和 局域网
 * 4. 域名:   www.baidu.com   www.mi.com  www.sina.com  www.jd.com
 *            www.vip.com
 * 5. 本地回路地址:127.0.0.1 对应着:localhost
 *
 * 6. 如何实例化InetAddress:两个方法:getByName(String host) 、 getLocalHost()
 *        两个常用方法:getHostName() / getHostAddress()
 *
 * 7. 端口号:正在计算机上运行的进程。
 * 要求:不同的进程有不同的端口号
 * 范围:被规定为一个 16 位的整数 0~65535。
 *
 * 8. 端口号与IP地址的组合得出一个网络套接字:Socket

网络通信协议

image.png

TCP协议:

  • 使用TCP协议前,须先建立TCP连接,形成传输数据通道
  • 传输前,采用“三次握手”方式,点对点通信,是可靠的
  • TCP协议进行通信的两个应用进程:客户端、服务端。
  • 在连接中可进行大数据量的传输
  • 传输完毕,需释放已建立的连接效率低

UDP协议:

  • 将数据、源、目的封装成数据包,不需要建立连接
  • 每个数据报的大小限制在64K内
  • 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
  • 可以广播发送
  • 发送数据结束时无需释放资源开销小速度快

Socket类的常用构造器:
 public Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
 public Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
Socket类的常用方法:
 public InputStream getInputStream()返回此套接字的输入流。可以用于接收网络消息
 public OutputStream getOutputStream()返回此套接字的输出流。可以用于发送网络消息
 public InetAddress getInetAddress()此套接字连接到的远程 IP 地址;如果套接字是未连接的,则返回 null。
 public InetAddress getLocalAddress()获取套接字绑定的本地地址。 即本端的IP地址
 public int getPort()此套接字连接到的远程端口号;如果尚未连接套接字,则返回 0。  public int getLocalPort()返回此套接字绑定到的本地端口。 如果尚未绑定套接字,则返回 -1。即本端的
端口号。
 public void close()关闭此套接字。套接字被关闭后,便不可在以后的网络连接中使用(即无法重新连接或重新绑定)。需要创建新的套接字对象。 关闭此套接字也将会关闭该套接字的 InputStream 和OutputStream。
 public void shutdownInput()如果在套接字上调用 shutdownInput() 后从套接字输入流读取内容,则流将返回 EOF(文件结束符)。 即不能在从此套接字的输入流中接收任何数据。
 public void shutdownOutput()禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流,则该流将抛出 IOException。 即不能通过此套接字的输出流发送任何数据。

TCP

image.png
客户端创建Socket对象
  • 客户端Socket的工作过程包含以下四个基本的步骤:
     创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
     打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用getOutputStream()方法获得输出流,进行数据传输
     按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
     关闭 Socket:断开客户端到服务器的连接,释放线路

  • 客户端程序可以使用Socket类创建对象,创建的同时会自动向服务器方发起连接
    Socket的构造器是:
    Socket(String host,int port)throws UnknownHostException,IOException:向服务器(域名是
    host。端口号为port)发起TCP连接,若成功,则创建Socket对象,否则抛出异常。
    Socket(InetAddress address,int port)throws IOException:根据InetAddress对象所表示的
    IP地址以及端口号port发起连接。
    客户端建立socketAtClient对象的过程就是向服务器发出套接字连接请求

//1.创建Socket对象,指明服务器端的ip和端口号
InetAddress inet = InetAddress.getByName("172.18.2.41");
Socket socket = new Socket(inet,8899);
//2.获取一个输出流,用于输出数据
os = socket.getOutputStream();
//3.写出数据的操作
os.write("你好,我是客户端".getBytes());
//资源的关闭
socket.close();
socket.close();

服务器建立 ServerSocket 对象
  • ServerSocket 对象负责等待客户端请求建立套接字连接,类似邮局某个窗口中的业务员。也就是说,服务器必须事先建立一个等待客户请求建立套接字连接的ServerSocket对象。
    所谓“接收”客户的套接字请求,就是accept()方法会返回一个 Socket 对象

//1.创建服务器端的ServerSocket,指明自己的端口号
ServerSocket ss = new ServerSocket(8899);
//2.调用accept()表示接收来自于客户端的socket
Socket socket= ss.accept();
//3.获取输入流
InputStream is = socket.getInputStream();
//4.读取输入流中的数据 -- 防止乱码
ByteArrayOutputStream baos= new ByteArrayOutputStream();
byte[] buffer = new byte[5];
int len;
while((len = is.read(buffer)) != -1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
System.out.println("收到了来自于:" + socket.getInetAddress().getHostAddress() + "的数据");
//关闭资源
baos.close();
is.close();
socket.close();

例子1:客户端发送信息给服务端,服务端将数据显示在控制台上
//客户端
    @Test
    public void client()  {
        Socket socket = null;
        OutputStream os = null;
        try {
            //1.创建Socket对象,指明服务器端的ip和端口号
            InetAddress inet = InetAddress.getByName("172.18.2.41");
            socket = new Socket(inet,8899);
            //2.获取一个输出流,用于输出数据
            os = socket.getOutputStream();
            //3.写出数据的操作
            os.write("你好,我是客户端".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源的关闭
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }



    }
    //服务端
    @Test
    public void server()  {

        ServerSocket ss = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            //1.创建服务器端的ServerSocket,指明自己的端口号
            ss = new ServerSocket(8899);
            //2.调用accept()表示接收来自于客户端的socket
            socket = ss.accept();
            //3.获取输入流
            is = socket.getInputStream();
            //4.读取输入流中的数据
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[5];
            int len;
            while((len = is.read(buffer)) != -1){
                baos.write(buffer,0,len);
            }

            System.out.println(baos.toString());

            System.out.println("收到了来自于:" + socket.getInetAddress().getHostAddress() + "的数据");

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(baos != null){
                //5.关闭资源
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

例题2:客户端发送文件给服务端,服务端将文件保存在本地。
/*
    这里涉及到的异常,应该使用try-catch-finally处理
     */
    @Test
    public void client() throws IOException {
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
        OutputStream os = socket.getOutputStream();
        FileInputStream fis = new FileInputStream(new File("beauty.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);
        }
        fis.close();
        os.close();
        socket.close();
    }

    /*
    这里涉及到的异常,应该使用try-catch-finally处理
     */
    @Test
    public void server() throws IOException {
        ServerSocket ss = new ServerSocket(9090);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("beauty1.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }
        fos.close();
        is.close();
        socket.close();
        ss.close();
    }

例题3:从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。
并关闭相应的连接。
        /*
        这里涉及到的异常,应该使用try-catch-finally处理
         */
    @Test
    public void client() throws IOException {
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
        OutputStream os = socket.getOutputStream();
        FileInputStream fis = new FileInputStream(new File("beauty.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer)) != -1){
            os.write(buffer,0,len);
        }
        //关闭数据的输出
        socket.shutdownOutput();

        //5.接收来自于服务器端的数据,并显示到控制台上
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] bufferr = new byte[20];
        int len1;
        while((len1 = is.read(buffer)) != -1){
            baos.write(buffer,0,len1);
        }

        System.out.println(baos.toString());

        fis.close();
        os.close();
        socket.close();
        baos.close();
    }

    /*
    这里涉及到的异常,应该使用try-catch-finally处理
     */
    @Test
    public void server() throws IOException {
        ServerSocket ss = new ServerSocket(9090);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("beauty2.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }

        System.out.println("图片传输完成");

        //6.服务器端给予客户端反馈
        OutputStream os = socket.getOutputStream();
        os.write("你好已收到".getBytes());

        fos.close();
        is.close();
        socket.close();
        ss.close();
        os.close();

    }

UDP

UDP协议的网路编程
 流 程:

  1. DatagramSocket与DatagramPacket
  2. 建立发送端,接收端
  3. 建立数据包
  4. 调用Socket的发送、接收方法
  5. 关闭Socket
    发送端与接收端是两个独立的运行程序

时间:2019-12-15 21:23:23

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容