黑马程序员-网络

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

1. 概述

网络编程的本质是两个设备之间的数据交换,在计算机网络中,设备主要指计算机。

  • 网络模型
    网络传输方式中所细致划分层次的一个传输模型。每个层次都有自己功能作用。

OSI和TVPIP参考模型.png

 1. OSI参考模型
     * 主要有七层定义:两个设备间通讯先会进行封装信息包的动作然后传给要传输的设备,接受设备在进行拆包动作对信息解析和接受。
 2. TCP/IP参考模型
     * 是对OSI模型的一个简化,分为四层。网络编程主要对应的是传输层和网际层。
     * 传输层对应的协议:TCP和UDP。网际层为:IP协议。应用层为HTTP、FTP等等协议。
  • 网络通讯要素
    1. IP地址:网络设备标识。本机回环IP地址:127.0.0.1或者localhost,也是默认。用途:可以测试网卡等。
    2. 端口:网络设备上应用程序的标识,此标识称作端口(逻辑端口),范围是0-65535任选,其中0-1024为系统使用或者保留端口。
    3. 传输协议:定义通信规则,此规则称为协议。常见的协议有:国际通用协议为:TCP/IP,UDP。
package com.sergio.Network;

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

/**
 * IP对象使用示例
 * Created by Sergio on 2015-05-19.
 */
public class IPDemo {
    public static void main(String[] args) {
        InetAddress i = null;
        InetAddress ia = null;
        try {
            i = InetAddress.getLocalHost();
            System.out.println(i.toString());
            System.out.println(i.getHostAddress());
            System.out.println(i.getHostName());

            //通过名称主机名来解析地址和名字。但是还是以ip地址为主
            ia = InetAddress.getByName("www.baidu.com");
            System.out.println(ia.getHostAddress());
            System.out.println(ia.getHostName());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

2. UDP和TCP

  • UDP:

    1. 将数据及源和目的封装成数据包,不需要建立连接
    2. 每个数据报的大小限制在64k内,有个封包动作
    3. 因无连接,是不可靠协议
    4. 不需要建立连接,速度快
    5. 应用场景:聊天,视频,桌面共享等
  • TCP:

    1. 建立连接,形成传输数据的通道
    2. 在连接中进行大数据量传输
    3. 通过三次握手完成连接,是可靠协议
    4. 必须建立连接,效率会稍低
    5. 应用场景:下载等

3. Socket

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

4. UDP应用

  • 对应的对象:DatagramSocket与DatagramPacket

  • 发送数据的步骤:

    1. 建立udp socket服务
    2. 提供数据,并将数据封装到数据包中
    3. 通过socket服务的发送功能,将数据包发出去
    4. 关闭资源
package com.sergio.Network;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * UDP发送数据步骤:
 * 1. 建立udp socket服务
 * 2. 提供数据,并将数据封装到数据包中
 * 3. 通过socket服务的发送功能,将数据包发出去
 * 4。关闭资源
 * Created by Sergio on 2015-05-19.
 */
public class UDPSendDataDemo {
    public static void main(String[] args) throws Exception {
        //socket服务建立
        DatagramSocket ds = new DatagramSocket();
        //提供数据
        byte[] data = "udp send".getBytes();
        //封装数据
        DatagramPacket dp =
            new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.123"), 10000);
        //发送数据
        ds.send(dp);
        ds.close();
    }
}
  • 接收数据的步骤:

    1. 定义UDP socket服务,通常会监听一个端口,用来接收该接受的应用程序
    2. 定义数据包,用来存储接收到是字节数据,因为数据包对象中有更多功能可以提取字节数据的不同信息,
    3. 通过socket服务的receive方法将接收到的数据存入一定以好数据包中,
    4. 通过数据包对象的特有功能,将这些不同的数据取出。
package com.sergio.Network;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * UDP接受数据步骤:
 * 1. 定义UDP socket服务,通常会监听一个端口,用来接收该接受的应用程序
 * 2. 定义数据包,用来存储接收到是字节数据,因为数据包对象中有更多功能可以提取字节数据的不同信息,
 * 3. 通过socket服务的receive方法将接收到的数据存入一定以好数据包中,
 * 4. 通过数据包对象的特有功能,将这些不同的数据取出。
 * Created by Sergio on 2015-05-19.
 */
public class UDPReceiveDataDemo {
    public static void main(String[] args) throws Exception {
        //创建udp socket服务,指定端口来接受该有的应用程序信息
        DatagramSocket ds = new DatagramSocket(10000);
        while (true) {
            //定义数据包,用来存储接受到的数据包
            byte[] data = new byte[1024];
            DatagramPacket dp = new DatagramPacket(data, data.length);
            //通过服务的receive方法将受到数据存入数据包中
            ds.receive(dp);
            //通过数据包的方法提取数据信息
            String ip = dp.getAddress().getHostAddress();
            //获取应有长度的数据内容
            String data1 = new String(dp.getData(), 0, dp.getLength());
            int port = dp.getPort();
            System.out.println(data1 + ip + port);
        }
    }
}
  • 练习聊天:
package com.sergio.Network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

/**
 * 聊天程序
 * Created by Sergio on 2015-05-19.
 */
public class ChatDemo {
    public static void main(String[] args) throws Exception {
        //创建发送和接受对象
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receiveSocket = new DatagramSocket(10002);
        //启动线程
        new Thread(new Send(sendSocket)).start();
        new Thread(new Receive(receiveSocket)).start();
    }
}


//发送数据端线程
class Send implements Runnable {
    private DatagramSocket ds;

    public Send(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            //读取键盘录入并发送数据
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            while ((line = br.readLine()) != null) {
                if ("886".equals(line))
                    break;

                byte[] buf = line.getBytes();
                DatagramPacket dp =
                    new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.123"), 10002);
                ds.send(dp);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}


//接受数据的线程
class Receive implements Runnable {
    private DatagramSocket ds;

    public Receive(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    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 (IOException e) {
            e.printStackTrace();
        }

    }
}

5. TCP应用

  • 对应的对象为:Socket和ServerSocket
  • TCP分客户端和服务端。客户端对应的对象为Socket、服务端为:ServerSocket。

    步骤:

  • 一. 客户端:
    1. 创建Socket服务,并指定要连接的主机和端口。
    2. 获取Socket流的中的输出流,将数据写到该流中,通过网络发送给服务端。
    3. 关闭Scoket。
    4. 二. 服务端:

    1. 建立服务端的Socket服务,ServerSocket();
    2. 获取连接过来的客户端对象,通过ServerSocket的accept方法连接,此方法是阻塞式的。
    3. 客户端如果发来数据,服务端需要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发来的数据。
    4. 关闭服务端(可选)。
  • 注意:服务端没有输入输出流,主要是利用客户端对象的输出输入流来读取数据信息。

package com.sergio.Network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 交互式客户端示例
 * Created by Sergio on 2015-05-20.
 */
public class TCPClientDemo2 {
    public static void main(String[] args) throws IOException {
        //建立Socket服务,指定连接主机和端口号
        Socket s = new Socket("192.168.1.123", 10004);
        //获取Socket流中的输出流,并写入到该流中
        OutputStream out = s.getOutputStream();
        out.write("交互式信息发送".getBytes());

        //交互部分代码输入,读取数据
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf, 0, len));
        s.close();

    }
}
package com.sergio.Network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 交互式服务端示例
 * Created by Sergio on 2015-05-20.
 */
public class TCPServerDemo2 {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket服务,并监听10004端口
        ServerSocket ss = new ServerSocket(10004);
        //通过accept方法获取客户端对象
        Socket s = ss.accept();
        //打印客户端的ip地址
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "连接进来");

        //获取客户端的输入流,并读取数据
        InputStream is = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        System.out.println(new String(buf, 0, len));

        //与客户端交互部分,写入数据
        OutputStream out = s.getOutputStream();
        out.write("服务端受到信息".getBytes());
        s.close();
        ss.close();
    }
}
  • 键盘录入数据服务端返回大写格式信息示例:
package com.sergio.Network;

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

/**
 * 将客户端发送给服务端的字符转成大写。注意读取键盘录入数据的结束标记换行和回车符。
 * Created by Sergio on 2015-05-20.
 */
public class TransClientDemo {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("192.168.1.123", 10005);
        //定义读取键盘数据的流对象
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //定义目的,将数据写入到socket输出流,发送给服务端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        //对上一句替换语句//PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
        //定义一个socket读取流,读取服务端返回的大写信息
        BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;
        while ((line = br.readLine()) != null) {
            if ("over".equals(line))
                break;
            bw.write(line);
            //需要有个回车符结束标记
            bw.newLine();
            bw.flush();
            //对上面三句的替换//pw.print(line);
            //读取服务端返回的信息
            String str = brIn.readLine();
            System.out.println("server::" + str);
        }
        br.close();
        s.close();
    }
}


package com.sergio.Network;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 将客户端发送给服务端的字符转成大写。注意读取键盘录入数据的结束标记换行和回车符。
 * Created by Sergio on 2015-05-20.
 */
public class TransServerDemo {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10005);
        Socket s = ss.accept();

        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "连接进来");

        //读取socket读取流中的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //目的socket输出流将大小数据写入到socket暑促胡柳,并发送给客户端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        //PrintWriter pw = new PrintWriter(s.getOutputStream());
        String line = null;
        while ((line = br.readLine()) != null) {
            //pw.print(line.toUpperCase());
            bw.write(line.toUpperCase());
            bw.newLine();
            bw.flush();
        }
        s.close();
        ss.close();
    }
}
  • 客户端登录服务器示例:
package com.sergio.Network;

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

/**
 * 上传图片示例,客户端
 * 步骤:1.服务端点,2.读取客户端已有的数据,3.通过Socket输出流将数据发给服务端,
 * 4.读取服务端发聩信息,5.关闭
 * Created by Sergio on 2015-05-22.
 */
public class UploadPicClient {
    public static void main(String[] args) throws Exception {
        //用来判断上传图片的上传要求
        //为空
        if (args.length != 1) {
            System.out.println("请选择一个jpg格式的图片");
            return;
        }
        File file = new File(args[0]);
        if (file.exists() && file.isFile()) {
            System.out.println("该文件有问题");
            return;
        }
        if (!file.getName().endsWith(".jpg")) {
            System.out.println("图片格式错误");
        }
        if (file.length() > 1024 * 1024 * 5) {
            System.out.println("文件过大");
            return;
        }

        Socket s = new Socket("192.168.1.123", 10008);
        FileInputStream fis = new FileInputStream(file);
        OutputStream out = s.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
        //告诉服务端数据已经传完
        s.shutdownOutput();

        //读取反馈的信息
        InputStream in = s.getInputStream();
        byte[] bufIn = new byte[1024];
        int num = in.read(bufIn);
        System.out.println(new String(bufIn, 0, num));
        fis.close();
        s.close();
    }
}

package com.sergio.Network;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 上传图片示例,并发处理服务端
 * Created by Sergio on 2015-05-22.
 */
public class UploadPicServer {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(10008);
        while (true) {
            //获取客户端连接并监听地址和端口
            Socket s = ss.accept();
            //启动服务端并发处理的线程
            new Thread(new PicThread(s)).start();
        }
    }
}


//服务端上传图片线程
class PicThread implements Runnable {
    private Socket s;

    PicThread(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        //用来重复上传图片计数
        int count = 1;
        String ip = s.getInetAddress().getHostAddress();
        try {
            System.out.println(ip + "连接进来了");
            InputStream in = s.getInputStream();
            //处理重复上传判断和处理
            File file = new File(ip + "(" + (count) + ")" + ".jpg");
            while (file.exists()) {
                file = new File(ip + "(" + (count++) + ")" + ".jpg");
            }
            //读取图片
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buf = new byte[1024];
            int len = 0;
            while ((len = in.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }

            //服务端回应客户端
            OutputStream out = s.getOutputStream();
            out.write("上传成功".getBytes());
            fos.close();
            s.close();
        } catch (Exception e) {
            throw new RuntimeException(ip + "上传失败");
        }
    }
}

URL和URLConnection

  • URL是对底层传输层功能封装的对象。
  • URLConnection相当于应用层对URL的功能封装,更简便。

1.URL

package com.sergio.Network;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * URL对象示例,对网址进行解析
 * Created by Sergio on 2015-05-24.
 */
public class URLDemo {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://www.amazon.cn/clouddrive?sf=1&ref_=nav_Photos_Files");
        System.out.println("协议" + url.getProtocol());
        System.out.println("主机" + url.getHost());
        System.out.println("端口" + url.getPort());
        System.out.println("路径" + url.getPath());
        System.out.println("文件" + url.getFile());
        System.out.println("查询" + url.getQuery());
    }
}

2.URLConnection

package com.sergio.Network;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 * URLConnection对象使用,对连接解析并获取网页内容。
 * Created by Sergio on 2015-05-24.
 */
public class URLConnectionDemo {
    public static void main(String[] args) throws IOException {
        URL url = new URL("https://www.amazon.cn.");
        //应用层URLConnection对象封装,打开socket流
        URLConnection conn = url.openConnection();
        System.out.println(conn);

        InputStream in = conn.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        //打印获取到的数据信息
        System.out.println(new String(buf, 0, len));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值