美文网首页
Java网络编程

Java网络编程

作者: 古拉啦啦 | 来源:发表于2019-08-21 23:10 被阅读0次

在正式讲解之前,我们先来看看一些基本基础知识,只有知道这些知识,才能更好的学习好网络编程,这些基础知识如下:

1.为什么需要网络编程

简单来说,需要在两台不同的计算机之间进行数据传递,所以需要网络编程。

2.常见的两种协议

TCP/IP:TCP 是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
UDP:UDP 是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据包。

Socket类:

1.服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。
2.服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
3.服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。
4.Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。
5.在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。

3. 举例说明客户端与服务端的区别:

客户端:例如手机APP 浏览器 桌面qq
服务器端:是用来存储/处理数据

4. URL:统一的资源定位

例如一个浏览器中的地址栏: http://www.baidu.com/search?code=android

  • http/https : 传输协议
  • www.baidu.com"域名,表示一台网络中的电脑
  • IPv4 IPv6 地址:唯一标识一台网络中的电脑
  • 32位:四个部分每个是8个字节《------》www.baidu.com
  • DNS服务器:域名解析, 功能是将诸如www.baidu.com解析为对应的ip地址
  • serach:对应的后台程序文件
  • ?需要传递的参数、
  • code = android code 之服务器端规定的字段
  • &如果有多个参数是用&符号来连接

5.IP地址和端口号

上面我们说过了IP地址,这里说一下端口号的作用:

从图可以看出,虽然指定了IP地址,但是还是不能我完成通信,所以,端口号就是解决图中的问题的。

利用网络实现的如下功能:

  • 1.固定内容发送
  • 2.服务器端手动输入内容发送
  • 3.向服务器端传送图片
  • 4.实现群聊功能

1,固定内容发送
客户端:

  class Client {
  public static void main(String[] args) throws IOException {
    //1.创建用于通信的socket
    //  指明和谁通信:ip地址  端口号
    Socket socket = new Socket("192.168.43.32",8989);
    // 接收服务器端的数据
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    //读取服务器端发来的数据
    String line = null;
    while ((line = br.readLine()) != null){
        System.out.println(line);
    }

    // 客户端向服务器端发送数据
    PrintStream ps = new PrintStream(socket.getOutputStream());
    ps.println("你好啊");
   socket.shutdownInput();
  }
}

服务器端:

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(clientSocket.getOutputStream()));
    PrintStream ps = new PrintStream(clientSocket.getOutputStream());
    ps.println("登录成功");
    //输出完毕
    clientSocket.shutdownInput();
    //4.接收客户端发来的数据
    BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    String line = null;
    while ((line = br.readLine()) != null){
        System.out.println(line);
      }
    }
}

解析:简单来说,实现网络编程,需要做的工作有以下几点:
客户端:

  • 创建用于通信的socket,指明IP地址,端口号,明确知道将要和谁通信。Socket socket= new Socket("192.168.43.32",9090);
  • 网络编程中,接收服务器端的数据。
  • 向服务器端传送数据。

以字符为例接收服务器端的数据的例子如下格式:

 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    //读取服务器端发来的数据
    String line = null;
    while ((line = br.readLine()) != null){
        System.out.println(line);
    }

想服务器端发送数据的例子格式如下:

 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    bw.write("你好啊");

或者:

    PrintStream ps = new PrintStream(socket.getOutputStream());
    ps.println("你好啊");

服务器端:
首先第一步:创建ServerSocket

ServerSocket serverSocket = new ServerSocket(9090)

第二步:获取连接服务器端的客户端的socket

 Socket socket = serverSocket.accept();

第三步:向客户端发送数据:

    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
    bw.write("登录成功");

或者:

 PrintStream ps = new PrintStream(clientSocket.getOutputStream());
 ps.println("登录成功");

第四步:从客户端接收数据:

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = null;
        while ((line = br.readLine())!=null){
            System.out.println(line);
        }

2,手动输入
客户端:

class  MyClient{
public static void main(String[]args){
    Socket socket= null;
    try {
         socket= new Socket("192.168.43.32",9090);  //链接服务器端de Socket
        //接受服务端的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = null;
        while ((line = br.readLine())!=null){
            System.out.println(line);
        }
        //发送从键盘的数据给服务器端
      BufferedReader Bw = new BufferedReader(new InputStreamReader(System.in));
        //获取服务端的输出流
        PrintStream ps = new PrintStream(socket.getOutputStream());
        String line1 = null;
        while ((line1 = Bw.readLine())!=null){
            ps.println(line);
        }


    } catch (IOException e) {
        System.out.print("网络出错,请重新登陆");
    }finally {
        //关闭连接
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  }
}

这段代码与固定发送给的代码相比,只有一小点不同,创建socket那些都是一样的,不一样的就是,要从输入端输入然后再发送给服务器端,传输对象,因为这样,所以多了判断的语句,其他的都一模一样。

发送从键盘的数据给服务器端
BufferedReader Bw = new BufferedReader(new InputStreamReader(System.in));

服务器端:

class MyServer{
public static void main(String[]args){
    //创建ServerSocket
      //写在try的圆括号里面,是因为它会自动关闭
    try( ServerSocket serverSocket = new ServerSocket(9090);) {
        //监听连接
     Socket socket = serverSocket.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();
    }

  }
}

同样这里也是,只是多了从输入端作为发送对象,其他的都是一样的逻辑。

3.向服务器端传送图片
客户端:

class Client{
public static void main(String[] args) throws IOException {
    //连接服务器 获取socket
    Socket socket = new Socket("192.168.43.32",8080);

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

    //向服务器端发送文件(图片)
    //1.将文件写入到内存里
    String path = "C:\\Users\\Administrator\\Desktop\\01.PNG";
    FileInputStream fis = new FileInputStream(path);  //从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();
  }
}

向服务器端发送图片的步骤:

  • 1.获取需要发送的图片的地址
  • 2.在当前文件中保存需要发送的图片
  • 3.以字节流的形式发送图片

获取需要发送的图片的地址

String path = "C:\\Users\\Administrator\\Desktop\\01.PNG";

在当前文件中保存需要发送的图片

FileInputStream fis = new FileInputStream(path);  

以字节流的形式发送图片

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);
    }

服务器端:

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 = "C:\\Users\\Administrator\\Desktop\\java\\java\\java1\\src\\main\\java\\day12\\radio\\02.PNG";
    FileOutputStream fos = new FileOutputStream(path);

    byte[] buf = new byte[1024];
    int len = -1;
    while((len = bis.read(buf)) != -1){
        fos.write(buf,0,len);
      }
    }
}

4,实现群聊
客户端

class  Client {
public static void main(String[] args) throws IOException {
    Socket socket = new Socket("192.168.43.32", 9999);
    //   用一个子线程处理服务器端的数据
    // 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;

    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.print(line);
            }
        } catch (IOException e) {
            System.out.print("网络错误,请重新登录");
            System.exit(-1);
        } finally {
            try {
                if (br != null){
                    br.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.print("网络出错,请重新登陆");
                System.exit(-1);
            }

        }
    }
}

服务器端:

class Server{
//保存每一个socket对象
public static ArrayList<Socket> sockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(9994);
    //不停的等待客户端来连接
    while (true) {
        Socket socket = serverSocket.accept();
        sockets.add(socket);
        new ServerThread(socket).start();
      }
    }
}

继承Thread 创建子线程

 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) {
        e.printStackTrace();
        System.out.print("网络异常,请重新登陆");
        System.exit(-1);
    } finally {
        try {
            if (br != null)
                br.close();
            if (socket != null)
                socket.close();
        } catch (IOException e) {
            e.printStackTrace();

          }
      }
  }
}

解析:实现这个群聊的功能,最重要的就是想到,怎样做到是群聊的效果,这里运用的是一个socket数组,一个统一的服务器端,是群聊消息的时候就遍历socket数组,给每个元素都发相同的消息。

 public static ArrayList<Socket> sockets = new ArrayList<>();

遍历:

    for(Socket s :Server.sockets){
                PrintStream ps = new PrintStream(s.getOutputStream());
                ps.println(line);

总结:对于之前没有学过网络编程的来说,这是一个新的知识点。刚开始学,还不能很好的与多线程,文件的操作等合理的集合起来。还需要大量的练习代码。

相关文章

  • Java网络编程(第四版) PDF 超清版

    《Java网络编程(第四版)》是一本关于Java编程相关的电子书资源,介绍了关于Java、网络编程、Java编程方...

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

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

  • Http协议

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

  • Chapter 12 . 网络编程

    阅读原文 Chapter 12 . 网络编程 12.1网络编程概述 • Java是 Internet ...

  • 《Netty实战》读书笔记01——第一章

    第 1 章 笔记 Java 网络编程 早期Java的网络编程,需要学习很多C语言套接字(Socket)的知识,但...

  • Java NIO

    书本 Netty权威指南netty实战O’Reilly的《Java nio》Unix网络编程 《unix网络编程》...

  • IO编程

    一、Java网络编程 https://www.runoob.com/java/java-networking.ht...

  • Java网络编程

    Java 网络编程 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。 java.net...

  • 动脑学院架构篇-Java Socket编程基础及深入讲解

    【Socket】Java Socket编程基础及深入讲解 Socket是Java网络编程的基础,了解还是有好处的,...

  • day26

    1:网络编程(理解)## (1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享 (2)网络编程模型 ...

网友评论

      本文标题:Java网络编程

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