美文网首页
[Java]开发安卓,你得掌握的Java知识13——网络基础

[Java]开发安卓,你得掌握的Java知识13——网络基础

作者: 入梦瞌睡 | 来源:发表于2019-08-21 23:26 被阅读0次

0.前言

  • 今天我们主要讲解一些网络基本概念

  • 这篇文章内容可能有点水,某些原因导致头昏脑胀,已经好几次差点昏过去了,但是还是得坚持写完,请大家多多谅解

  • 若想要了解“类”等其他主要知识,可以去看前面的文章

  • 由于最终目的是要开发安卓app,
    因此这里使用的IDE是AS(Android Studio)
    (不会使用的可以参考下面这篇文章中的例子)
    [Java]开发安卓,你得掌握的Java知识2

1.文章主要内容

  • 网络的基本概念简单讲解

  • 用AS完成简单的服务器端与客户端的交互


2.基础知识讲解

网络相关概念简介

  • URL:
    统一的资源定位,用于找服务器中的某个资源

  • http/https:
    超文本传输协议(HyperText Transfer Protocol)
    一种传输时候需要遵循的协议

  • TCP/IP协议
    它是传输层协议,主要解决数据如何在网络中传输,
    而HTTP是应用层协议,主要解决如何包装数据。

  • DNS服务器:
    域名解析,将"www.baidu.com"类型的域名解析为对应的ip地址

  • ip地址
    某台电脑的ip地址,能找到这台网络中该电脑的位置

  • 端口号:
    端口号就是用来标识这台电脑上的某个进程
    比如QQ的端口号为1
    依靠电脑的ip地址和端口号1,就可以访问这台电脑的QQ

客户端与服务器.png
  • 套接字(socket)
    是一个抽象层,应用程序可以通过它发送或接收数据
    客户端用的是Socket类,而服务器端用的是ServerSocket类

客户端方面:

Socket类的方法 具体描述
getInputStream 得到一个输入流,即得到从服务器端发回的数据。
getOutputStream 得到一个输出流,即得到发送给服务器端的数据。

服务器端端方面:

Socket类的方法 具体描述
getInputStream 得到从客户端发送给服务器端的数据流。
getOutputStream 得到发送给客户端的数据。

3.服务器端与客户端的简单交互

第一步

在MyClient中创建一个主函数,并且在主函数中创建客户端Socket类对象
构造方法中,第一个参数是欲访问的ip地址,第二个参数是欲访问的端口

public class MyClient{
       public static void main(String[] args){
              Socket socket = new Socket("127.0.0.1",9090);
       }  
}

第二步

在MyServer中创建一个主函数,并且在主函数中创建客户端ServerSocket类对象
构造方法中,参数是服务器端开放的端口

public class MyServer{
       public static void main(String[] args){
              ServerSocket ss = new ServerSocket(9090);
              Socket socket = ss.accept();
       }  
}

第三步

写一个MessageManager类,里面写两个函数:
getTerminalMessageAndSent(Socket socket)

getMessageFromOppsite(Socket socket)

public void getTerminalMessageAndSent(Socket socket) throws IOException {
        BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        PrintStream ps = new PrintStream(socket.getOutputStream());
        while ((line = keyIn.readLine()) != null) {
            ps.println(line);
        }
        ps.close();
        keyIn.close();
    }
  • 注意:
    (1)BufferedReader的构造方法中需要一个Reader,因此,使用new InputStreamReader()将字节流转成字符流
    (2)这个函数主要功能是:获得终端输入的信息并且输出给对面
    (3)PrintStream的作用就是通过print()或者println()将内容输出给对方
    (4)line = keyIn.readLine()意思是将终端输入的内容赋值给line,然后用ps.println输出
    (5)socket.getOutputStream()表示得到想要发送出去的数据
 public void getMessageFromOppsite(Socket socket){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 注意:
    (1)BufferedReader是用来接收传过来的信息的,所以后面用的是socket.getInputStream(),即获得传入的数据
    (2)new InputStreamReader可以将InputStream转换为Reader,以此来初始化BufferedReader
    (3)line = br.readLine(),可以将读到的内容赋值给line,然后使用System.out.println()输出
    (4)可以使用readLine()的理由是:上面第一个函数中用的是println()

第四步

创建一个Client类,里面写一个静态的socket

public Client{
    public static Socket socket;
    static {
        try {
            socket = new Socket("127.0.0.1",9090);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

创建一个,Server类,同上

public class Server {
    public static ServerSocket serverSocket;
    public static Socket socket;
static {
        try {
            serverSocket = new ServerSocket(9090);
            socket = serverSocket.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

第五步

为Client写两个类,这两个类实现了Runnable接口,即可以放在不同的线程中,以此实现服务端与客户端的实时交互

public class ClientGet implements Runnable{

    @Override
    public void run() {
        MessageManager.instance.getMessageFromOppsite(Client.socket);
        ClientManager.countNow++;
        //super.run();
    }
}


public class ClientSent implements Runnable{
    @Override
    public void run() {
        try {
            MessageManager.instance.getTerminalMessageAndSent(Client.socket);
            ClientManager.countNow++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

为Server类同理

public class ServerGet implements Runnable{

    @Override
    public void run() {
        try {
         MessageManager.instance.getMessageFromOppsite(Server.socket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


public class ServerSent implements Runnable{
    @Override
    public void run() {
        try {
        MessageManager.instance.getMessageFromOppsite(Server.socket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

第六步

在MyClient中实现两个子线程,MyServer中同理

public class MyClient {
    public static void main(String[] args) {
        ClientGet cg = new ClientGet();
        ClientSent ct = new ClientSent();

        Thread t = new Thread(cg);
        Thread t2 = new Thread(ct);

        t.start();
        t2.start();
    }
}
public class MyServer {
    public static void main(String[] args) {
        ServerGet sg = new ServerGet();
        ServerSent ss = new ServerSent();

        Thread t = new Thread(sg);
        Thread t2 = new Thread(ss);

        t.start();
        t2.start();
    }
}

最后

先开启MyServer中的main函数,再开启MyClient的,然后,就可以在终端进行交互了,在MyServer的终端输入的内容,可以在MyClient中看到,反之亦然。

4.总结

(1)本文讲解一些网络的简单概念,以及服务器端和客户端的交互相关知识
(2)其实服务器端和客户端交互的基础逻辑概念并不难理解,关键还是在于各种输入流和输出流的运用,必须搞清楚什么时候该用哪种流
(3)只有多练习,才能熟练整个交互过程,为日后安卓开发打下良好的基础

相关文章

网友评论

      本文标题:[Java]开发安卓,你得掌握的Java知识13——网络基础

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