美文网首页
JAVA-网络编程1(基础知识详解)

JAVA-网络编程1(基础知识详解)

作者: 宁晓鸯 | 来源:发表于2019-08-21 23:23 被阅读0次

心得体会

  • 今天学的东西挺有趣的,从简单的服务端与客户端模拟,到实现群聊,一步一步感觉demo实现的功能越来越多。同一段的代码,不厌其烦的反复敲,与其他代码组合起来,就实现了不同的功能^^
    --

今日所学

  • 1.OSI与TCP/IP体系模型

  • 2.URL

  • 3.IP地址和端口

  • 4.TCP和UDP

  • 5.Socket

  • 6.服务器端和客户端(聊天小demo)

具体操作

1.OSI与TCP/IP体系模型

image.png
image.png

2.URL

URL的定义

URL是统一资源定位符(Uniform Resource Locator,缩写为URL),又叫做网页地址,是互联网上标准的资源的地址(Address)。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

URL的组成
PVF1_B{`M{4SFAN`04DAUJG.png

http://www.baidu.com/search?code=android

http:——指定因特网服务的类型。最流行的类型是HTTP
www.baidu.com——域名 表示一台网络中的电脑
search——URL的这部分被称为层级文件路径
code=android —— 查询字符串是一个非必须的字段,只要负责将一系列非层级格式的任意参数传给服务器。可同时传递多个参数,参数之间用“&"符号连接,每个参数名与值用 = 隔开
& ——如果有多个参数使用&符号链接 例如: www.baidu.com?uid=777&qqq=666


3.IP地址和端口号

  • 1、IP地址用于唯一标示网络中的一个通信实体。这个通信实体可以是一台主机,可以是一台打印机,或者是路由器的某一个端口。而在基于IP协议网络中传输的数据包,必须使用IP 地址来进行标示。IP地址就像写一封信,必须指定收件人的地址一样。每个被传输的数据包中都包括了一个源IP和目标IP。
  • 2、IP地址唯一标示了通信实体,但是一个通信实体可以有多个通信程序同时提供网络服务。这个时候就要通过端口来区分开具体的通信程序。一个通信实体上不能有两个通信程序,使用同一个端口号。
  • 3.IP地址和端口号,就像一个出差去外地入住酒店一样,IP地址表示了酒店在具体位置,而端口号则表示了这个人在酒店的房间号。

4.TCP和UDP

1、TCP是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。它能够提供两台计算机之间的可靠的数据流,HTTP、FTP、Telnet等应 用都需要这种可靠的通信通道。

2、UDP是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传送目的地,至于能够达到目的地,达到目的地的时间以及内容的正确性都是不能保证的。

既然有了保证可靠传输的TCP协议,为什么还要非可靠传输的UDP协议呢?原因有两个:

  • 1、可靠的传输是要付出代价的,对数据内容的正确性的检验必然会占用计算机处理时间和网络带宽。因此TCP的传输效率不如UDP高。
  • 2、许多应用中并不需要保证严格的传输可靠性,比如视频会议系统,并不要求视频音频数据绝对正确,只要能够连贯就可以了。所以在这些场景下,使用UDP更合适些。

5.Socket

Socket定义

套接字(通讯双方C/S协商好的约定),网络上两个程序通过一个双向的通信连接实现数据的交换,这个链接的一端称为一个Socket。应用程序通过套接字向网络发出请求或者应答网络请求。

image.png
网络通信的要素
  • 网络请求就是通过Socket建立连接然后互相通信

①IP地址(主机的唯一标识)
②端口号(定位程序,标示不同的进程)
③传输协议(通讯的规则)[常见的协议:TCP、UDP]


2.服务器端和客户端

服务器端和客户端的定义与联系
  • 服务器端:

服务端是为客户端服务的,服务的内容诸如向客户端提供资源,保存客户端数据。例如:手机的存储、数据处理

  • 客户端:

客户端(Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。除了一些只在本地运行的应用程序之外,一般安装在普通的客户机上,需要与服务器端互相配合运行 例如:手机app 浏览器 桌面QQ

客户端、服务器端模拟
demo1—实现客户端和服务器端传递数据:( 注意端⼝号必须相同 先运⾏Server 再运⾏Client)
  • 服务器端
  • 1.新建一个Server类,并在类中写一个main方法
  • 2.创建服务器端的ServerSocket(直接创建一个ServerSocket对象,并写一个端口 ) (注意:端口的值不能太大,否则会出现异常!!!)
  • 3.获取连接的客户端的socket
  • 4.向客户端发送数据
  • 5.接收客户端发来的数据
//模拟服务器端
class Server{
    public static void main(String[] args)throws IOException{
        //1.创建服务器端的ServerSocket
        ServerSocket ss=new ServerSocket(8989);

        //2.获取连接的客户端的socket
        Socket clientSocket=ss.accept();

        //3.向客户端发送数据
        //BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(cilentSocket.getOutputStream()));
        PrintStream ps=new PrintStream(clientSocket.getOutputStream());
        ps.println("登录成功");
        clientSocket.shutdownOutput();
        //4.接收客户端发来的数据
        BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String line=null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
    }
}

ps:

  • 1.在创建ServerSocket对象时会出现 异常,这时需要抛出异常或自己处理异常,上图代码采取的是系统自动抛出异常
  • 2.向客户端发送数据有两种方式,一种用BufferedWriter,一种用 **PrintStream**
  • 3.向客户端发送数据后需要关闭数据

  • 客户端:
  • 1.新建一个Client类
  • 2.创建用于通信的socket (指明和谁通信:ip地址 端口号)
  • 3.接收服务器端的数据
  • 4.读取服务器端发来的数据
  • 5.客户端向服务器端发送数据
class Client{
    public static void main(String[] args) throws IOException {
        //1.创建用于通信的socket
        //指明和谁通信:ip地址 端口号
        Socket socket=new Socket("192.168.43.121",8989);
        //接收服务器端的数据
       BufferedReader br=new BufferedReader( new InputStreamReader(socket.getInputStream()));
        //读取服务器端发来的数据
       // socket.getOutputStream();
        String line =null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
        //客户端向服务器端发送数据
        PrintStream ps=new PrintStream(socket.getOutputStream());
        ps.println("你好啊!");
        socket.shutdownOutput();
    }
}

ps:

  • 1.在创建Socket对象时会出现 异常,这时需要抛出异常或自己处理异常,上图代码采取的是系统自动抛出异常
  • 2.向服务器端发送数据后需要关闭数据

运行结果:


13X5Q9@V9${O__R@$NZPKA5.png
image.png
demo2—实现服务器端⼿动输⼊,将输⼊的内容发送给客户端 ,可以⼀直发( 注意端⼝号必须相同 先运⾏Server 再运⾏Client)
  • 服务器端
class MyServer{
    public static void main(String[] args){
        //创建ServerSocket
        try (ServerSocket ss = new ServerSocket(8888)){
            //监听客户端的连接
            Socket socket = ss.accept();

            //从终端接收数据
            BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
            //获取向客户端输出数据的输出流
            PrintStream ps = new PrintStream(socket.getOutputStream());
            String line = null;

            while ((line = keyin.readLine()) != null){
                //发送给客户端
                ps.println(line);
            }

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

}
  • 客户端:
class Myclient{
    public static void main(String[] args){
        //连接服务器端的socket
        Socket socket = null;
        try{
            socket = new Socket("192.168.43.121",8888);

            //接收服务器端信息
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }

            //从键盘输入数据 发送给服务器端
        } catch (IOException e) {
            System.out.println("网络出错 请重新登录");
        } finally {
            //关闭连接
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

PS:

  • 1.创建的对象的时候有异常,此时应该捕获异常,并且最后还要用finally来关闭(finally是必须执行的,有清理资源等作用),finally有异常进行捕获
  • 2.**demo1与demo2最大的区别是demo2实现了从终端输入
    BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
    运行结果
    20190821_221949.gif
demo3—实现客户端向服务器端上传图⽚
  • 服务器端
class Server{
    public static void main(String[] args) throws IOException {
        //创建服务器端的ServerSoket
        ServerSocket ss = new ServerSocket(8080);

        //监听客户端连接
        //当有客户端来连接这个服务器 就可以得到对应的socket
        //当没有客户端来连接 服务器一直在这里等待
        Socket socket = ss.accept();

        //创建客户端对应的输出流 用于向这个客户端发送数据
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println("连接成功 可以发数据了!");

        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        String path = "F:/JAVA/DAY12/Day1/src/main/java/Day12/java/media/1.jpg";
        FileOutputStream fos = new FileOutputStream(path);

        byte[] buf = new byte[1024];
        int len = -1;
        while((len = bis.read(buf)) != -1){
            fos.write(buf,0,len);
        }
    }
}
  • 客户端:
class Client{
    public static void main(String[] args) throws IOException {
        //连接服务器 获取socket
        Socket socket = new Socket("192.168.43.121",8080);

        //创建服务器端对应的输入流 用于接收服务器端发来的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(br.readLine());

        //向服务器端发送文件(图片)
        //1.将文件写入到内存里
        String path = "C:/Users/Administrator.000/Desktop/psd/4456d40b75f2f8b4";
        FileInputStream fis = new FileInputStream(path);

        //2.创建字节流 outputStream
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        byte[] buf = new byte[1024];
        int len = -1;
        while ((len = fis.read(buf)) != -1){
            bos.write(buf,0,len);
        }
        socket.shutdownOutput();
    }
}
7$Q(QXO8O`DV1A284FI5`Y4.png U5BV(){G)`CG_I4KV{_85MV.png
PS:
  • 我选择图片时用png格式不能成功,如果用png格式不行,可以换一个格式看看

demo4—使⽤多线程实现对聊

为什么要用多线程实现?

  • 聊天的过程是双向,同时进行的
class Client{
    public static void main(String[] args)throws IOException {
        Socket socket=new Socket("192.168.43.121",8888);
        //用一个子线程处理服务器端数据
        new Thread(new ClientThread(socket)).start();

        //主线程处理终端输入发送给服务器端
        BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
        PrintStream ps=new PrintStream(socket.getOutputStream());
        String line=null;
        while((line=keyin.readLine())!=null){
            ps.println(line);
        }
    }
}

/**
 * 创建一个子线程处理客户端接收服务器端数据
 */
class ClientThread implements Runnable{
    private Socket socket;
    //保存操作socket
    public ClientThread(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        BufferedReader br=null;
        try {
             br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //读取数据
            String line=null;
            while((line=br.readLine())!=null){
                System.out.println(line);
            }
        }catch(IOException e){
            System.out.println("网络出错 请重新登录");
            System.exit(-1);
        }finally{
            try {
                if (br != null) {
                    br.close();
                }
                if(socket!=null) {
                    socket.close();
                }
            }catch(IOException e){
                e.printStackTrace();
                }
         }
    }
}
class Server{
    public static void main(String[] args)throws IOException{
        ServerSocket ss=new ServerSocket(8888);
        //获取客户端的socket
        Socket socket= ss.accept();

        new ServerThread(socket).start();

        //从终端输入流对象
        BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
        //客户端的输出流对象
        PrintStream ps=new PrintStream(socket.getOutputStream());

        //读取终端的输入 将输入输出给客户端
        String line=null;
        while((line=keyin.readLine())!=null){
            ps.println(line);
        }
    }
}
/**
 * 服务器端创建一个子线程处理服务器端接受客户端的数据
 */
class ServerThread extends Thread{
    private Socket socket;
    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br =null;
        try {
             br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line=null;
                while((line=br.readLine())!=null){
                    System.out.println(line);
            }
        }catch(IOException e){
            System.out.println("网络出错 请重新登录");
            System.exit(-1);
        }finally{
            try {
                if (br != null) {
                    br.close();
                }
                if(socket!=null) {
                    socket.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

PS:

  • 1.上图的demo中创建子线程用了继承Thread的方法
    运行结果:


    ![`]E13M5$OXFI)N2MF2N368E.png
image.png
demo4—实现群聊
  • Client和ClientThread代码和对聊不变,主要在Server⾥添加数组和监听客户端连接


    2ZPYR{~)(5IS2J_AEAVR_QG.jpg
class server{
    public static ArrayList<Socket> sockets=new ArrayList<>();
    public static void main(String[] args)throws IOException {
        ServerSocket ss=new ServerSocket(6666);

        //不停的等待用户端连接
        while(true) {
            Socket socket = ss.accept();
            //当有客户端连接过来了 就保存
            sockets.add(socket);

            //开启一个线程处理每个客户端的输入
            new ServerThread(socket).start();
        }
    }
}
/**
 * 服务器端创建一个子线程处理服务器端接受客户端的数据
 */
class ServerThread extends Thread{
    private Socket socket;
    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br =null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line=null;
            while((line=br.readLine())!=null){
                //群发消息
                //遍历数组
                for(Socket s:server.sockets){
                    PrintStream ps=new PrintStream(s.getOutputStream());
                    ps.println(line);
                }
            }
        }catch(IOException e){
            System.out.println("网络出错 请重新登录");
            System.exit(-1);
        }finally{
            try {
                if (br != null) {
                    br.close();
                }
                if(socket!=null) {
                    socket.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}
class Client{
    public static void main(String[] args)throws IOException {
        Socket socket=new Socket("192.168.43.121",6666);
        //用一个子线程处理服务器端数据
        new Thread(new ClientThread(socket)).start();

        //主线程处理终端输入发送给服务器端
        BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
        PrintStream ps=new PrintStream(socket.getOutputStream());
        String line=null;
        while((line=keyin.readLine())!=null){
            ps.println(line);
        }


    }

}

/**
 * 创建一个子线程处理客户端接收服务器端数据
 */
class ClientThread implements Runnable{
    private Socket socket;
    //保存操作socket
    public ClientThread(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        BufferedReader br=null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //读取数据
            String line=null;
            while((line=br.readLine())!=null){
                System.out.println(line);
            }
        }catch(IOException e){
            System.out.println("网络出错 请重新登录");
            System.exit(-1);
        }finally{
            try {
                if (br != null) {
                    br.close();
                }
                if(socket!=null) {
                    socket.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}
20190821_231418.gif
PS:
  • 所连接的所有客户端,端口号必须一致!!!

相关文章

  • JAVA-网络编程1(基础知识详解)

    心得体会 今天学的东西挺有趣的,从简单的服务端与客户端模拟,到实现群聊,一步一步感觉demo实现的功能越来越多。同...

  • Android应用开发:网络编程2

    网络编程 Java基础:网络编程 Uri、URL、UriMatcher、ContentUris详解 Android...

  • Http协议

    网络编程 Java基础:网络编程 Uri、URL、UriMatcher、ContentUris详解 Android...

  • Java编程基础(11)

    Java编程基础知识:Java内置包装内 1.Java Object类详解:Object类的常用方法(equals...

  • Java-网络编程

    网络参考模型 网络要素-IP地址 网络要素-域名解析 TCP和UDP UDP 应用 发送端 接收端

  • java-网络编程

    1、Java支持基于流的通信和基于包的通信 基于流的通信使用TCP协议(传输控制协议)进行数据传输,传输是无损可靠...

  • IO

    java网络编程 阻塞IO NIO 1. java网络编程 基础知识1.ip地址和端口号2.tcp/udp协议3....

  • IO

    一、java网络编程 基础知识/Socket 1.基础知识 1)IP地址和端口号(区分具体的通信程序) 2)TCP...

  • python元编程详解

    注:采转归档,自己学习查询使用 python元编程详解(1)python元编程详解(2)python元编程详解(3...

  • 网络入门

    一、网络基础知识介绍 1、为什么要学习网络编程?---pptx介绍。 2、网络的基本概念---pptx介绍。 >什...

网友评论

      本文标题:JAVA-网络编程1(基础知识详解)

      本文链接:https://www.haomeiwen.com/subject/pphisctx.html