java 网络编程

1. 网络通信概述

可以参考link中的第二点网络基础

1.1 软件的结构

  1. C/S 结构:客户端、服务器

  2. B/S 结构: 浏览器、服务器

1.2 网络通信协议

  1. 网络通信协议
    一个网络中的计算机需要通信,他们需要遵循一些规则
    在计算机中这些链接通信规则就称之为网络通信协议
    他们对数据的传输格式,传输速率,传输步骤等统一规定,通信双方必须同时遵循这些规则才能通信

  2. TCP/IP协议

    又称为 传输控制协议,因特网互联协议

    定义了计算机如何介入因特网,数据在节点之间传输的标准
    内部包含一系列用于处理数据通信的协议,采用了4层的分层模型,每层都呼叫自己的下一层为自己提供协议完成自己的需求

链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动

网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。

运输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。

应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。

1.3 协议分类

  1. UDP——无连接通信协议
    1. 发送端给接收段发送数据不需要接收端同意,也不会判断是否存在
    2. 耗资少,通信效率高 通常用于音视频和普通数据的传输 视频会议、视频聊天一般都采用的UDP协议
      偶尔会丢一两个数据包,但对结果不会与太大影响。
    3. 因为UDP的无连接性,所有我们传输重要数据时最好不要用UDP协议
  1. TCP——面向连接通信协议
    在传输数据之前会先建立连接,然后才会开始传输数据,可以提供两个节点之间无差错的数据传输。
    三次握手:
    1. 客户端向服务端发送连接请求,等待服务器确认
    2. 服务端向客户端发送一个响应,回应收到了请求
    3. 客户端再次向服务端发送已经收到确认信息的响应,确认建立连接
      通过三次握手建立连接后,客户端与服务端就可以进行数据传输了。因为此特性,TCP协议可以保证传输数据的安全

1.4网络编程的3要素

  1. 协议
    计算机网络通信必须遵循的规则,详情见上述

  2. IP地址
    互联网协议地址,设备的唯一编号
    ipV4:32位
    ipV6:128位

  3. 端口号

  • 指定了ip只能准确的找到计算机,但是计算机上有很多的软件。
  • 如何准确的与计算机上的软件进行通信呢?
  • ip:端口 就可以准确的找到软件
  • 1024之前的端口基本上被已知软件占用
  • 端口不能多个软件共同使用
  • 端口的范围为 0——65535

2. TCP协议

TCP通信能实现两台计算机之间进行数据交换,通信的两端,严格的区分客户端和服务端

TCP通信: 面向连接的通信,客户端和服务端必须进行三次握手才能建立逻辑连接,才能安全通信

2.1 通信的步骤:

  1. 服务器先启动,服务器不会主动发起对客户段的连接。
  2. 客户端发起请求,客户端与服务端就会建立一个逻辑连接
    连接中包括一个对象——IO对象
  3. 客户端与服务端就可以使用
    传输的数据不限于字符,所以IO对象是字节流对象

2.2 服务端必须明确的事情

  1. 多个客户端与服务端进行交互时,服务端必须明确是哪个客户端与其交互
    在服务端有一个方法叫,accept可以获取到请求客户端对象
  2. 多个客户端与服务器进行交互时,就需要使用多个IO流对象
    服务端是没有IO流的,服务端可以获取到发起请求的客户端的Socket对象,从而使用每个客户端中的Socket中提供的IO流与客户端进行交互
    • 服务器使用客户端的字节输入流读取客户端发送的数据
    • 服务器使用客户端的字节输出流给客户端会写数据
      简单说就是服务器使用客户端的流进行交互
image.png

code:

  1. TcpClient服务类
public class TcpClient {
    public static void main(String[] args) throws IOException {
        //1. 创建一个客户端对象Socket,构造方法写入IP地址和端口号
        Socket socket = new Socket("127.0.0.1",8888);

        //2. 使用Socket对象中的 方法getOutputStream();获取到网络字节输出流
        OutputStream outputStream = socket.getOutputStream();

        //3. 使用网络字节输出流中的write方法来给服务器发送数据
        outputStream.write("你好服务器!!".getBytes());

        //拿到回复
        InputStream inputStream = socket.getInputStream();

        //读取类容
        ReaderMsg.readers(inputStream);

        // 释放资源
        socket.close();
    }
}
  1. TcpServer 服务类
public class TcpServer {
    public static void main(String[] args) throws IOException {
        //创建服务器对象ServerSocket,并通过构造方法指定端口号
        ServerSocket serverSocket = new ServerSocket(8888);

        //使用ServerSocket中的accpet方法来得到客户端的Socket对象
        Socket socket = serverSocket.accept();

        //使用Socket中的getInputStream();方法来获取到网络输入流
        InputStream inputStream = socket.getInputStream();

        //读取类容
        ReaderMsg.readers(inputStream);

        //使用Socket中的getOutputStream();方法来获取到网络输出流
        OutputStream outputStream = socket.getOutputStream();

        outputStream.write("我收到你的问候!".getBytes());

        //关闭流
        socket.close();
        serverSocket.close();

    }
}
  1. 字符输出类
public class ReaderMsg {
    public static void readers(InputStream inputStream) throws IOException {
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        System.out.println(new String(bytes,0,len));
    }
}

3. 综合案例_文件上传

客户端:

public class TcpFileClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8888);
        OutputStream outputStream = socket.getOutputStream();

        BufferedInputStream biStream = new BufferedInputStream(
                new FileInputStream("I:\\download\\myeclise-2018.8.0破解文件-小笨\\readme.txt"));

        System.out.println("客户端:我开始向服务器上传数据");

        byte[] bytes = new byte[512];
        int lenth = 0;
        while ((lenth = biStream.read(bytes))!=-1){
            outputStream.write(bytes,0,lenth);
        }
        //不写的话服务器将不知道什么时候才将文件上传结束
        socket.shutdownOutput();

        InputStream inputStream = socket.getInputStream();

        lenth = 0;
        while ((lenth = inputStream.read(bytes))!=-1){
            System.out.println(new String(bytes,0,lenth));
        }

        System.out.println("客户端:数据上传完毕");

        biStream.close();
        socket.close();
    }
}

服务端:

public class TcpFileServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);

        Socket socket = serverSocket.accept();
        InputStream inputStream = socket.getInputStream();

        File file = new File("I:\\chenpengFiles\\test");
        if (!file.exists()){
            file.mkdirs();
        }

        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                new FileOutputStream(file+"//test.txt"));
        System.out.println("服务器:开始上传文件");
        byte[] bytes = new byte[512];
        int lenth = 0;
        while ((lenth = inputStream.read(bytes))!=-1){
            bufferedOutputStream.write(bytes,0,lenth);
        }

        socket.getOutputStream().write("文件上传成功!".getBytes());

        System.out.println("服务器:文件上传成功");
        bufferedOutputStream.close();
        socket.close();
        serverSocket.close();
    }
}

优化版:

public class TcpFileServerThread {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);

        while (true){
            Socket socket = serverSocket.accept();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream inputStream = socket.getInputStream();

                        File file = new File("I:\\chenpengFiles\\test");
                        if (!file.exists()){
                            file.mkdirs();
                        }
                        String fileName = "\\"+new Random().nextInt(99999)+".txt";
                        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                                new FileOutputStream(file+fileName));
                        System.out.println("服务器:开始上传文件");
                        byte[] bytes = new byte[512];
                        int lenth = 0;
                        while ((lenth = inputStream.read(bytes))!=-1){
                            bufferedOutputStream.write(bytes,0,lenth);
                        }

                        socket.getOutputStream().write("文件上传成功!".getBytes());

                        System.out.println("服务器:文件上传成功");
                        bufferedOutputStream.close();

                    }catch (IOException e){
                        System.out.println(e.getMessage());
                        throw new RuntimeException();
                    }finally {
                        try {
                            socket.close();
                        }catch (Exception e){
                            throw new RuntimeException();
                        }
                    }
                }
            }).start();
        }
    }
}

4. 模拟BS服务器案例

code:

public class WebServer {
    private String paths = "H:\\javaCode\\ideaCode\\java2019\\demo\\src\\com\\looc\\demo12网络编程\\demo2\\";

    public void webServer() throws IOException {
        ServerSocket serverSocket = new ServerSocket(80);

        //监听事件
        while (true){
            //拿到socket对象
            Socket socket = serverSocket.accept();

            //开启多线程提高效率
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream inputStream = socket.getInputStream();

                        //读响应体
                        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"US-ASCII"));

                        //读取到文件
                        String str = br.readLine().split(" ")[1].substring(1);
                        BufferedInputStream bfs = new BufferedInputStream(
                                new FileInputStream(paths+str));

                        //回显
                        OutputStream oStream = socket.getOutputStream();
                        oStream.write("HTTP/1.1 200 OK\r\n".getBytes());
                        oStream.write("Content-Type:text/html\r\n".getBytes());
                        oStream.write("\r\n".getBytes());

                        byte[] bytes = new byte[1024];
                        int len = 0;
                        while ((len = bfs.read(bytes))!=-1){
                            oStream.write(bytes,0,len);
                        }
                        //关闭流
                        bfs.close();
                        br.close();
                    }catch (Exception e){
                        System.out.println(e.getMessage());
                    }finally {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

        }
    }


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

推荐阅读更多精彩内容

  • 计算机网络概述 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输。 按照计算机网络的定义,通过一定...
    蛋炒饭_By阅读 1,227评论 0 10
  • 网络编程的概述 网络编程的实质就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。 一.OSI网络模型...
    思念挥霍阅读 378评论 0 0
  • 1.网络编程1.1计算机网络概述网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输。按照计算机网络的...
    任振铭阅读 427评论 0 1
  • 一直想成为一个精致的猪猪女孩,但总是有很多借口,阻止了我,比如说太胖,太忙,太穷。 今天休...
    若夏城雨阅读 169评论 0 0
  • 我坐在地板上,迎面吹着风。看着操场,这里将是我大学三年呆的地方。 此刻,我没有新生那股带着对大学各种新奇的期盼,更...
    忆遗阅读 223评论 3 0